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