• 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/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