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/inner_navigation_controller.h"
17
18 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
19
20 namespace OHOS {
21 namespace Ace {
22 namespace {
23 constexpr int32_t INVALID_HANDLE = 0;
24 }
InnerNavigationController(const WeakPtr<NG::NavigationPattern> & pattern,int32_t containerId)25 InnerNavigationController::InnerNavigationController(
26 const WeakPtr<NG::NavigationPattern>& pattern, int32_t containerId)
27 : weakNavigationPattern_(pattern), containerId_(containerId) {}
28
IsNavDestinationInTopStack()29 bool InnerNavigationController::IsNavDestinationInTopStack()
30 {
31 return GetTopHandle() != INVALID_HANDLE;
32 }
33
GetTopHandle()34 int32_t InnerNavigationController::GetTopHandle()
35 {
36 CHECK_RUN_ON(UI);
37 ContainerScope scope(containerId_);
38 auto navigationPattern = weakNavigationPattern_.Upgrade();
39 CHECK_NULL_RETURN(navigationPattern, INVALID_HANDLE);
40 auto navigationStack = navigationPattern->GetNavigationStack();
41 CHECK_NULL_RETURN(navigationStack, INVALID_HANDLE);
42 auto topNavDestinationNode = navigationStack->GetTopNavPath();
43 if (!topNavDestinationNode.has_value()) {
44 return INVALID_HANDLE;
45 }
46
47 auto navDestinationNode = AceType::DynamicCast<NG::NavDestinationGroupNode>(
48 NG::NavigationGroupNode::GetNavDestinationNode(topNavDestinationNode->second));
49 CHECK_NULL_RETURN(navDestinationNode, INVALID_HANDLE);
50 return topNavDestinationNode->second->GetId();
51 }
52
SetInPIPMode(int32_t handle)53 void InnerNavigationController::SetInPIPMode(int32_t handle)
54 {
55 CHECK_RUN_ON(UI);
56 ContainerScope scope(containerId_);
57 auto navigationPattern = weakNavigationPattern_.Upgrade();
58 CHECK_NULL_VOID(navigationPattern);
59 auto navigationStack = navigationPattern->GetNavigationStack();
60 CHECK_NULL_VOID(navigationStack);
61 auto cacheNode = navigationStack->GetFromCacheNode(handle);
62 if (cacheNode.has_value()) {
63 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "The node has in cache");
64 return;
65 }
66
67 const auto& navDestinationNodes = navigationStack->GetAllNavDestinationNodes();
68 for (size_t i = 0; i != navDestinationNodes.size(); ++i) {
69 const auto& childNode = navDestinationNodes[i];
70 const auto& uiNode = childNode.second;
71 if (uiNode && uiNode->GetId() == handle) {
72 auto navDestination = AceType::DynamicCast<NG::NavDestinationGroupNode>(
73 NG::NavigationGroupNode::GetNavDestinationNode(uiNode));
74 if (navDestination == nullptr) {
75 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "The node is not navDestination node");
76 return;
77 }
78
79 navigationStack->AddCacheNode(childNode.first, uiNode);
80 return;
81 }
82 }
83 }
84
PopInPIP(bool destroy)85 void InnerNavigationController::PopInPIP(bool destroy)
86 {
87 CHECK_RUN_ON(UI);
88 ContainerScope scope(containerId_);
89 auto navigationPattern = weakNavigationPattern_.Upgrade();
90 CHECK_NULL_VOID(navigationPattern);
91 auto navigationStack = navigationPattern->GetNavigationStack();
92 CHECK_NULL_VOID(navigationStack);
93 auto topNavDestinationNode = navigationStack->GetTopNavPath();
94 if (!topNavDestinationNode.has_value()) {
95 return;
96 }
97
98 if (destroy && topNavDestinationNode->second) {
99 navigationStack->RemoveCacheNode(topNavDestinationNode->second->GetId());
100 }
101
102 navigationStack->Pop();
103 }
104
PushInPIP(int32_t handle)105 void InnerNavigationController::PushInPIP(int32_t handle)
106 {
107 CHECK_RUN_ON(UI);
108 ContainerScope scope(containerId_);
109 auto navigationPattern = weakNavigationPattern_.Upgrade();
110 CHECK_NULL_VOID(navigationPattern);
111 auto navigationStack = navigationPattern->GetNavigationStack();
112 CHECK_NULL_VOID(navigationStack);
113 auto topNavDestinationNode = navigationStack->GetTopNavPath();
114 if (topNavDestinationNode.has_value()) {
115 if (topNavDestinationNode->second && topNavDestinationNode->second->GetId() == handle) {
116 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "The node has in top stack");
117 return;
118 }
119 }
120 auto cacheNode = navigationStack->GetFromCacheNode(handle);
121 if (!cacheNode.has_value()) {
122 return;
123 }
124
125 navigationStack->ReOrderCache(cacheNode->first, cacheNode->second);
126 auto context = PipelineContext::GetCurrentContext();
127 CHECK_NULL_VOID(context);
128
129 auto nodePairs = navigationStack->GetAllNavDestinationNodes();
130 bool findPipNode = false;
131 int32_t nativeStackIndex = 0;
132 for (const auto& pair : nodePairs) {
133 if (pair.first == cacheNode->first && pair.second->GetId() == handle) {
134 findPipNode = true;
135 break;
136 }
137 nativeStackIndex++;
138 }
139
140 if (findPipNode) {
141 int32_t jsIndex = navigationStack->GetJsIndexFromNativeIndex(nativeStackIndex);
142 if (jsIndex < 0) {
143 navigationStack->Push(cacheNode->first);
144 } else {
145 navigationStack->MoveIndexToTop(jsIndex);
146 }
147 } else {
148 navigationStack->Push(cacheNode->first);
149 }
150 }
151
DeletePIPMode(int32_t handle)152 void InnerNavigationController::DeletePIPMode(int32_t handle)
153 {
154 CHECK_RUN_ON(UI);
155 ContainerScope scope(containerId_);
156 auto navigationPattern = weakNavigationPattern_.Upgrade();
157 CHECK_NULL_VOID(navigationPattern);
158 auto navigationStack = navigationPattern->GetNavigationStack();
159 CHECK_NULL_VOID(navigationStack);
160 auto context = NG::PipelineContext::GetCurrentContext();
161 CHECK_NULL_VOID(context);
162
163 auto task = [weakStack = AceType::WeakClaim(AceType::RawPtr(navigationStack)), handle]() {
164 auto stack = weakStack.Upgrade();
165 CHECK_NULL_VOID(stack);
166 stack->RemoveCacheNode(handle);
167 };
168 context->AddBuildFinishCallBack(task);
169 }
170 } // namespace Ace
171 } // namespace OHOS
172