• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "core/components_ng/pattern/navigation/navigation_stack.h"
17 
18 #include "core/components_ng/pattern/navrouter/navrouter_group_node.h"
19 
20 namespace OHOS::Ace::NG {
21 namespace {
22 constexpr int32_t NOT_EXIST = -1;
23 }
Remove()24 void NavigationStack::Remove()
25 {
26     if (navPathList_.empty()) {
27         return;
28     }
29     navPathList_.pop_back();
30     Pop();
31 }
32 
Remove(const std::string & name)33 void NavigationStack::Remove(const std::string& name)
34 {
35     if (navPathList_.empty()) {
36         return;
37     }
38     for (auto it = navPathList_.begin(); it != navPathList_.end();) {
39         if (((*it).first) == name) {
40             it = navPathList_.erase(it);
41         } else {
42             ++it;
43         }
44     }
45     RemoveName(name);
46 }
47 
Remove(const std::string & name,const RefPtr<UINode> & navDestinationNode)48 void NavigationStack::Remove(const std::string& name, const RefPtr<UINode>& navDestinationNode)
49 {
50     int32_t index = RemoveInNavPathList(name, navDestinationNode);
51     if (index != NOT_EXIST) {
52         RemoveIndex(index);
53     }
54 }
55 
RemoveInNavPathList(const std::string & name,const RefPtr<UINode> & navDestinationNode)56 int32_t NavigationStack::RemoveInNavPathList(const std::string& name, const RefPtr<UINode>& navDestinationNode)
57 {
58     int32_t index = NOT_EXIST;
59     if (!navPathList_.empty()) {
60         index = FindIndex(name, navDestinationNode, true);
61     }
62     if (index != NOT_EXIST) {
63         auto it = navPathList_.begin() + index;
64         navPathList_.erase(it);
65     }
66     return index;
67 }
68 
RemoveInPreNavPathList(const std::string & name,const RefPtr<UINode> & navDestinationNode)69 int32_t NavigationStack::RemoveInPreNavPathList(const std::string& name, const RefPtr<UINode>& navDestinationNode)
70 {
71     int32_t index = NOT_EXIST;
72     if (!preNavPathList_.empty()) {
73         index = FindIndex(name, navDestinationNode, false);
74     }
75     if (index != NOT_EXIST) {
76         auto it = preNavPathList_.begin() + index;
77         preNavPathList_.erase(it);
78     }
79     return index;
80 }
81 
RemoveIndex(int32_t index)82 void NavigationStack::RemoveIndex(int32_t index) {}
83 
Add(const std::string & name,const RefPtr<UINode> & navDestinationNode,NavRouteMode mode,const RefPtr<RouteInfo> & routeInfo)84 void NavigationStack::Add(const std::string& name, const RefPtr<UINode>& navDestinationNode, NavRouteMode mode,
85     const RefPtr<RouteInfo>& routeInfo)
86 {
87     if (mode == NavRouteMode::PUSH) {
88         Add(name, navDestinationNode, routeInfo);
89     } else if (mode == NavRouteMode::PUSH_WITH_RECREATE) {
90         AddForDefault(name, navDestinationNode, routeInfo);
91     } else if (mode == NavRouteMode::REPLACE) {
92         AddForReplace(name, navDestinationNode, routeInfo);
93     }
94 }
95 
96 #if defined(ENABLE_NAV_SPLIT_MODE)
isLastListContains(const std::string & name,const RefPtr<UINode> & navDestinationNode)97 bool NavigationStack::isLastListContains(
98     const std::string& name, const RefPtr<UINode>& navDestinationNode)
99 {
100     if (lastNavPathList_.empty()) {
101         return false;
102     }
103     // find from top to bottom
104     for (auto it = lastNavPathList_.rbegin(); it != lastNavPathList_.rend(); ++it) {
105         if ((*it).first == name && (*it).second == navDestinationNode) {
106             return true;
107         }
108     }
109     return false;
110 }
111 #endif
112 
Add(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)113 void NavigationStack::Add(
114     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
115 {
116     // for the old page: keep the UINode, and keep in the stack
117     auto index = FindIndex(name, navDestinationNode, true);
118     if (index != NOT_EXIST) {
119         RemoveIndex(index);
120         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "This navigation destination node already exists");
121     }
122     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
123     if (index != NOT_EXIST) {
124         Push(name, index);
125     } else {
126         Push(name, routeInfo);
127     }
128 }
129 
AddForDefault(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)130 void NavigationStack::AddForDefault(
131     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
132 {
133     // for the old page: destroy the UINode, but keep in the stack
134     auto index = FindIndex(name, navDestinationNode, true);
135     if (index != NOT_EXIST) {
136         RemoveIndex(index);
137     }
138     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
139     // push param into JSNavigationStack
140     if (index != NOT_EXIST) {
141         Push(name, index);
142     } else {
143         Push(name, routeInfo);
144     }
145 }
146 
AddForReplace(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)147 void NavigationStack::AddForReplace(
148     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
149 {
150     // for the old page: destroy the UINode, and move out of the stack
151     if (navPathList_.empty()) {
152         Add(name, navDestinationNode);
153         return;
154     }
155     auto index = FindIndex(name, navDestinationNode, true);
156     if (index != NOT_EXIST) {
157         navPathList_.pop_back(); // move the old page
158         RemoveIndex(index);
159     } else {
160         navPathList_.pop_back();
161     }
162     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
163 
164     Pop();
165     if (index != NOT_EXIST) {
166         Push(name, index);
167     } else {
168         Push(name, routeInfo);
169     }
170 }
171 
RemoveAll()172 void NavigationStack::RemoveAll()
173 {
174     navPathList_.clear();
175     Clear();
176 }
177 
FindIndex(const std::string & name,const RefPtr<UINode> & navDestinationNode,bool isNavPathList)178 int32_t NavigationStack::FindIndex(
179     const std::string& name, const RefPtr<UINode>& navDestinationNode, bool isNavPathList)
180 {
181     NavPathList navPathList = isNavPathList ? navPathList_ : preNavPathList_;
182     if (navPathList.empty()) {
183         return NOT_EXIST;
184     }
185     int32_t index = static_cast<int32_t>(navPathList.size()) - 1;
186     // find from top to bottom
187     for (auto it = navPathList.rbegin(); it != navPathList.rend(); ++it) {
188         if ((*it).first == name && (*it).second == navDestinationNode) {
189             return index;
190         }
191         --index;
192     }
193     return NOT_EXIST;
194 }
195 
Get()196 RefPtr<UINode> NavigationStack::Get()
197 {
198     if (navPathList_.empty()) {
199         return nullptr;
200     }
201     int32_t top = static_cast<int32_t>(navPathList_.size()) - 1;
202     return navPathList_[top].second;
203 }
204 
Get(const std::string & name,RefPtr<UINode> & navDestinationNode,int32_t & index)205 bool NavigationStack::Get(const std::string& name, RefPtr<UINode>& navDestinationNode, int32_t& index)
206 {
207     // from bottom to top
208     if (navPathList_.empty()) {
209         navDestinationNode = nullptr;
210         index = NOT_EXIST;
211         return false;
212     }
213     int32_t curIndex = 0;
214     for (auto it = navPathList_.begin(); it != navPathList_.end(); ++it) {
215         if ((*it).first == name) {
216             navDestinationNode = (*it).second;
217             index = curIndex;
218             return true;
219         }
220         curIndex++;
221     }
222     navDestinationNode = nullptr;
223     index = NOT_EXIST;
224     return false;
225 }
226 
Get(int32_t index)227 RefPtr<UINode> NavigationStack::Get(int32_t index)
228 {
229     if (index < 0 || index >= Size()) {
230         return nullptr;
231     }
232     return navPathList_[index].second;
233 }
234 
GetNavDesNameByIndex(int32_t index)235 std::string NavigationStack::GetNavDesNameByIndex(int32_t index)
236 {
237     if (index < 0 || index >= Size()) {
238         return "";
239     }
240     return navPathList_[index].first;
241 }
242 
GetFromPreBackup(const std::string & name,RefPtr<UINode> & navDestinationNode,int32_t & index)243 bool NavigationStack::GetFromPreBackup(const std::string& name, RefPtr<UINode>& navDestinationNode, int32_t& index)
244 {
245     // from bottom to top
246     if (preNavPathList_.empty()) {
247         navDestinationNode = nullptr;
248         index = NOT_EXIST;
249         return false;
250     }
251     int32_t curIndex = 0;
252     for (auto it = preNavPathList_.begin(); it != preNavPathList_.end(); ++it) {
253         if ((*it).first == name) {
254             navDestinationNode =  (*it).second;
255             index = curIndex;
256             return true;
257         }
258         curIndex++;
259     }
260     navDestinationNode = nullptr;
261     index = NOT_EXIST;
262     return false;
263 }
264 
GetPre(const std::string & name,const RefPtr<UINode> & navDestinationNode)265 RefPtr<UINode> NavigationStack::GetPre(const std::string& name, const RefPtr<UINode>& navDestinationNode)
266 {
267     if (navPathList_.empty() || navPathList_.size() == 1) {
268         return nullptr;
269     }
270     auto index = FindIndex(name, navDestinationNode, true);
271     if (index == 0 || index == NOT_EXIST) {
272         // no more navDestinationNode in front or no this navDestinationNode
273         return nullptr;
274     } else {
275         --index;
276         return navPathList_[index].second;
277     }
278 }
279 
IsEmpty()280 bool NavigationStack::IsEmpty()
281 {
282     return false;
283 }
284 
Pop()285 void NavigationStack::Pop() {}
286 
GetAllPathName()287 std::vector<std::string> NavigationStack::GetAllPathName()
288 {
289     if (navPathList_.empty()) {
290         return {};
291     }
292     std::vector<std::string> pathNames;
293     for (const auto& path : navPathList_) {
294         pathNames.emplace_back(path.first);
295     }
296     return pathNames;
297 }
298 
GetAllPathIndex()299 std::vector<int32_t> NavigationStack::GetAllPathIndex()
300 {
301     if (navPathList_.empty()) {
302         return {};
303     }
304     std::vector<int32_t> pathIndex;
305     for (int32_t i = 0; i < static_cast<int32_t>(navPathList_.size()); i++) {
306         pathIndex.emplace_back(i);
307     }
308     return pathIndex;
309 }
Push(const std::string & name,const RefPtr<RouteInfo> & routeInfo)310 void NavigationStack::Push(const std::string& name, const RefPtr<RouteInfo>& routeInfo) {}
311 
Push(const std::string & name,int32_t index)312 void NavigationStack::Push(const std::string& name, int32_t index) {}
313 
RemoveName(const std::string & name)314 void NavigationStack::RemoveName(const std::string& name) {}
315 
Clear()316 void NavigationStack::Clear()
317 {
318     navPathList_.clear();
319     cacheNodes_.clear();
320 }
321 
CreateNodeByIndex(int32_t index,const WeakPtr<UINode> & customNode,RefPtr<UINode> & node)322 bool NavigationStack::CreateNodeByIndex(int32_t index, const WeakPtr<UINode>& customNode, RefPtr<UINode>& node)
323 {
324     return false;
325 }
326 
CreateNodeByRouteInfo(const RefPtr<RouteInfo> & routeInfo,const WeakPtr<UINode> & node)327 RefPtr<UINode> NavigationStack::CreateNodeByRouteInfo(const RefPtr<RouteInfo>& routeInfo, const WeakPtr<UINode>& node)
328 {
329     return nullptr;
330 }
331 
UpdateReplaceValue(int32_t value) const332 void NavigationStack::UpdateReplaceValue(int32_t value) const {}
333 
GetReplaceValue() const334 int32_t NavigationStack::GetReplaceValue() const
335 {
336     return 0;
337 }
338 
GetAllCacheNodes()339 NavPathList NavigationStack::GetAllCacheNodes()
340 {
341     return cacheNodes_;
342 }
343 
AddCacheNode(const std::string & name,const RefPtr<UINode> & uiNode)344 void NavigationStack::AddCacheNode(
345     const std::string& name, const RefPtr<UINode>& uiNode)
346 {
347     if (name.empty() || uiNode == nullptr) {
348         return;
349     }
350 
351     auto navDestination = AceType::DynamicCast<NG::NavDestinationGroupNode>(
352         NG::NavigationGroupNode::GetNavDestinationNode(uiNode));
353     if (navDestination) {
354         navDestination->SetIsCacheNode(true);
355     }
356 
357     cacheNodes_.emplace_back(std::make_pair(name, uiNode));
358 }
359 
RemoveCacheNode(int32_t handle)360 void NavigationStack::RemoveCacheNode(int32_t handle)
361 {
362     if (handle <= 0) {
363         return;
364     }
365 
366     for (auto it = cacheNodes_.begin(); it != cacheNodes_.end(); ++it) {
367         if ((*it).second->GetId() == handle) {
368             auto navDestination = AceType::DynamicCast<NG::NavDestinationGroupNode>(
369                 NG::NavigationGroupNode::GetNavDestinationNode(it->second));
370             if (navDestination) {
371                 navDestination->SetIsCacheNode(false);
372             }
373             cacheNodes_.erase(it);
374             return;
375         }
376     }
377 }
378 
RemoveCacheNode(NavPathList & cacheNodes,const std::string & name,const RefPtr<UINode> & navDestinationNode)379 void NavigationStack::RemoveCacheNode(
380     NavPathList& cacheNodes, const std::string& name, const RefPtr<UINode>& navDestinationNode)
381 {
382     if (cacheNodes.empty() || name.empty() || navDestinationNode == nullptr) {
383         return;
384     }
385 
386     for (auto it = cacheNodes.begin(); it != cacheNodes.end(); ++it) {
387         if ((*it).first == name || (*it).second == navDestinationNode) {
388             cacheNodes.erase(it);
389             return;
390         }
391     }
392 }
393 
ReOrderCache(const std::string & name,const RefPtr<UINode> & navDestinationNode)394 void NavigationStack::ReOrderCache(const std::string& name, const RefPtr<UINode>& navDestinationNode)
395 {
396     if (name.empty() || navDestinationNode == nullptr) {
397         return;
398     }
399 
400     auto cacheNodes = cacheNodes_;
401     cacheNodes_.clear();
402     cacheNodes_.emplace_back(std::make_pair(name, navDestinationNode));
403     for (auto it = cacheNodes.begin(); it != cacheNodes.end(); ++it) {
404         if ((*it).first == name && (*it).second == navDestinationNode) {
405             continue;
406         }
407 
408         cacheNodes_.emplace_back(std::make_pair((*it).first, (*it).second));
409     }
410 }
411 
GetFromCacheNode(NavPathList & cacheNodes,const std::string & name)412 RefPtr<UINode> NavigationStack::GetFromCacheNode(
413     NavPathList& cacheNodes, const std::string& name)
414 {
415     if (cacheNodes.empty() || name.empty()) {
416         return nullptr;
417     }
418     for (auto it = cacheNodes.begin(); it != cacheNodes.end(); ++it) {
419         if ((*it).first == name) {
420             return (*it).second;
421         }
422     }
423     return nullptr;
424 }
425 
GetFromCacheNode(const std::string & name)426 RefPtr<UINode> NavigationStack::GetFromCacheNode(const std::string& name)
427 {
428     if (name.empty()) {
429         return nullptr;
430     }
431     for (auto it = cacheNodes_.begin(); it != cacheNodes_.end(); ++it) {
432         if ((*it).first == name) {
433             return (*it).second;
434         }
435     }
436     return nullptr;
437 }
438 
GetFromCacheNode(int32_t handle)439 std::optional<std::pair<std::string, RefPtr<UINode>>> NavigationStack::GetFromCacheNode(int32_t handle)
440 {
441     for (auto it = cacheNodes_.begin(); it != cacheNodes_.end(); ++it) {
442         if ((*it).second && (*it).second->GetId() == handle) {
443             return std::make_pair((*it).first, (*it).second);
444         }
445     }
446     return std::nullopt;
447 }
448 
DumpStackInfo() const449 std::vector<std::string> NavigationStack::DumpStackInfo() const
450 {
451     std::vector<std::string> dumpInfos;
452     for (size_t i = 0; i < navPathList_.size(); ++i) {
453         const auto& name = navPathList_[i].first;
454         std::string info = "[" + std::to_string(i) + "]{ name: \"" + name + "\" }";
455         dumpInfos.push_back(std::move(info));
456     }
457     return dumpInfos;
458 }
459 } // namespace OHOS::Ace::NG
460