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 <utility>
19
20 #include "core/components_ng/pattern/navrouter/navrouter_group_node.h"
21 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
22
23 namespace OHOS::Ace::NG {
24 namespace {
25 constexpr int32_t NOT_EXIST = -1;
26 }
Remove()27 void NavigationStack::Remove()
28 {
29 if (navPathList_.empty()) {
30 return;
31 }
32 navPathList_.pop_back();
33 Pop();
34 }
35
Remove(const std::string & name)36 void NavigationStack::Remove(const std::string& name)
37 {
38 if (navPathList_.empty()) {
39 return;
40 }
41 for (auto it = navPathList_.begin(); it != navPathList_.end();) {
42 if (((*it).first) == name) {
43 it = navPathList_.erase(it);
44 } else {
45 ++it;
46 }
47 }
48 RemoveName(name);
49 }
50
Remove(const std::string & name,const RefPtr<UINode> & navDestinationNode)51 void NavigationStack::Remove(const std::string& name, const RefPtr<UINode>& navDestinationNode)
52 {
53 int32_t index = RemoveInNavPathList(name, navDestinationNode);
54 if (index != NOT_EXIST) {
55 RemoveIndex(index);
56 }
57 }
58
RemoveInNavPathList(const std::string & name,const RefPtr<UINode> & navDestinationNode)59 int32_t NavigationStack::RemoveInNavPathList(const std::string& name, const RefPtr<UINode>& navDestinationNode)
60 {
61 int32_t index = NOT_EXIST;
62 if (!navPathList_.empty()) {
63 index = FindIndex(name, navDestinationNode, true);
64 }
65 if (index != NOT_EXIST) {
66 auto it = navPathList_.begin() + index;
67 navPathList_.erase(it);
68 }
69 return index;
70 }
71
RemoveInPreNavPathList(const std::string & name,const RefPtr<UINode> & navDestinationNode)72 int32_t NavigationStack::RemoveInPreNavPathList(const std::string& name, const RefPtr<UINode>& navDestinationNode)
73 {
74 int32_t index = NOT_EXIST;
75 if (!preNavPathList_.empty()) {
76 index = FindIndex(name, navDestinationNode, false);
77 }
78 if (index != NOT_EXIST) {
79 auto it = preNavPathList_.begin() + index;
80 preNavPathList_.erase(it);
81 }
82 return index;
83 }
84
RemoveIndex(int32_t index)85 void NavigationStack::RemoveIndex(int32_t index) {}
86
Add(const std::string & name,const RefPtr<UINode> & navDestinationNode,NavRouteMode mode,const RefPtr<RouteInfo> & routeInfo)87 void NavigationStack::Add(const std::string& name, const RefPtr<UINode>& navDestinationNode, NavRouteMode mode,
88 const RefPtr<RouteInfo>& routeInfo)
89 {
90 if (mode == NavRouteMode::PUSH) {
91 Add(name, navDestinationNode, routeInfo);
92 } else if (mode == NavRouteMode::PUSH_WITH_RECREATE) {
93 AddForDefault(name, navDestinationNode, routeInfo);
94 } else if (mode == NavRouteMode::REPLACE) {
95 AddForReplace(name, navDestinationNode, routeInfo);
96 } else {
97 LOGW("unsupported navRouteMode");
98 }
99 }
100
Add(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)101 void NavigationStack::Add(
102 const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
103 {
104 // for the old page: keep the UINode, and keep in the stack
105 auto index = FindIndex(name, navDestinationNode, true);
106 if (index != NOT_EXIST) {
107 LOGW("This navDestination node already exists");
108 Remove(name, navDestinationNode);
109 }
110 navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
111 if (index != NOT_EXIST) {
112 Push(name, index);
113 } else {
114 Push(name, routeInfo);
115 }
116 }
117
AddForDefault(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)118 void NavigationStack::AddForDefault(
119 const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
120 {
121 // for the old page: destroy the UINode, but keep in the stack
122 auto index = FindIndex(name, navDestinationNode, true);
123 auto top = static_cast<int32_t>(navPathList_.size()) - 1;
124 if (top != NOT_EXIST) {
125 auto oldName = navPathList_[top].first;
126 navPathList_.pop_back();
127 navPathList_.emplace_back(std::make_pair(oldName, nullptr));
128 }
129
130 if (index != NOT_EXIST) {
131 Remove(name, navDestinationNode);
132 }
133 navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
134 // push param into JSNavigationStack
135 if (index != NOT_EXIST) {
136 Push(name, index);
137 } else {
138 Push(name, routeInfo);
139 }
140 }
141
AddForReplace(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)142 void NavigationStack::AddForReplace(
143 const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
144 {
145 // for the old page: destroy the UINode, and move out of the stack
146 if (navPathList_.empty()) {
147 Add(name, navDestinationNode);
148 return;
149 }
150 auto index = FindIndex(name, navDestinationNode, true);
151 if (index != NOT_EXIST) {
152 navPathList_.pop_back(); // move the old page
153 Remove(name, navDestinationNode);
154 } else {
155 navPathList_.pop_back();
156 }
157 navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
158
159 Pop();
160 if (index != NOT_EXIST) {
161 Push(name, index);
162 } else {
163 Push(name, routeInfo);
164 }
165 }
166
RemoveAll()167 void NavigationStack::RemoveAll()
168 {
169 navPathList_.clear();
170 Clear();
171 }
172
FindIndex(const std::string & name,const RefPtr<UINode> & navDestinationNode,bool isNavPathList)173 int32_t NavigationStack::FindIndex(
174 const std::string& name, const RefPtr<UINode>& navDestinationNode, bool isNavPathList)
175 {
176 NavPathList navPathList = isNavPathList ? navPathList_ : preNavPathList_;
177 if (navPathList.empty()) {
178 return NOT_EXIST;
179 }
180 int32_t index = navPathList.size() - 1;
181 // find from top to bottom
182 for (auto it = navPathList.rbegin(); it != navPathList.rend(); ++it) {
183 if ((*it).first == name && (*it).second == navDestinationNode) {
184 return index;
185 }
186 --index;
187 }
188 return NOT_EXIST;
189 }
190
Get()191 RefPtr<UINode> NavigationStack::Get()
192 {
193 if (navPathList_.empty()) {
194 return nullptr;
195 }
196 int32_t top = navPathList_.size() - 1;
197 return navPathList_[top].second;
198 }
199
Get(const std::string & name)200 RefPtr<UINode> NavigationStack::Get(const std::string& name)
201 {
202 // from bottom to top
203 if (navPathList_.empty()) {
204 return nullptr;
205 }
206 for (auto it = navPathList_.begin(); it != navPathList_.end(); ++it) {
207 if ((*it).first == name) {
208 return (*it).second;
209 }
210 }
211 return nullptr;
212 }
213
GetFromPreBackup(const std::string & name)214 RefPtr<UINode> NavigationStack::GetFromPreBackup(const std::string& name)
215 {
216 // from bottom to top
217 if (preNavPathList_.empty()) {
218 return nullptr;
219 }
220 for (auto it = preNavPathList_.begin(); it != preNavPathList_.end(); ++it) {
221 if ((*it).first == name) {
222 return (*it).second;
223 }
224 }
225 return nullptr;
226 }
227
GetPre(const std::string & name,const RefPtr<UINode> & navDestinationNode)228 RefPtr<UINode> NavigationStack::GetPre(const std::string& name, const RefPtr<UINode>& navDestinationNode)
229 {
230 if (navPathList_.empty() || navPathList_.size() == 1) {
231 return nullptr;
232 }
233 auto index = FindIndex(name, navDestinationNode, true);
234 if (index == 0 || index == NOT_EXIST) {
235 // no more navDestinationNode in front or no this navDestinationNode
236 return nullptr;
237 } else {
238 --index;
239 return navPathList_[index].second;
240 }
241 }
242
IsEmpty()243 bool NavigationStack::IsEmpty()
244 {
245 return false;
246 }
247
Pop()248 void NavigationStack::Pop() {}
249
GetAllPathName()250 std::vector<std::string> NavigationStack::GetAllPathName()
251 {
252 if (navPathList_.empty()) {
253 return {};
254 }
255 std::vector<std::string> pathNames;
256 for (const auto& path : navPathList_) {
257 pathNames.emplace_back(path.first);
258 }
259 return pathNames;
260 }
261
Push(const std::string & name,const RefPtr<RouteInfo> & routeInfo)262 void NavigationStack::Push(const std::string& name, const RefPtr<RouteInfo>& routeInfo) {}
263
Push(const std::string & name,int32_t index)264 void NavigationStack::Push(const std::string& name, int32_t index) {}
265
RemoveName(const std::string & name)266 void NavigationStack::RemoveName(const std::string& name) {}
267
Clear()268 void NavigationStack::Clear()
269 {
270 navPathList_.clear();
271 }
272
CreateNodeByIndex(int32_t index)273 RefPtr<UINode> NavigationStack::CreateNodeByIndex(int32_t index)
274 {
275 return nullptr;
276 }
277
CreateNodeByRouteInfo(const RefPtr<RouteInfo> & routeInfo)278 RefPtr<UINode> NavigationStack::CreateNodeByRouteInfo(const RefPtr<RouteInfo>& routeInfo)
279 {
280 return nullptr;
281 }
282 } // namespace OHOS::Ace::NG
283