1 /*
2  * Copyright (c) 2024 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 "bridge/cj_frontend/cppview/native_view.h"
17 
18 #include "bridge/cj_frontend/runtime/cj_runtime_delegate.h"
19 #include "core/components_ng/base/view_partial_update_model.h"
20 #include "core/components_ng/base/view_stack_model.h"
21 #include "core/components_ng/pattern/custom/custom_measure_layout_node.h"
22 
23 namespace OHOS::Ace::Framework {
24 
GetProcessViewId(int64_t id)25 std::string GetProcessViewId(int64_t id)
26 {
27     return ViewStackModel::GetInstance()->ProcessViewId(std::to_string(id));
28 }
29 
NativeView(sptr<RemoteView> cjView)30 NativeView::NativeView(sptr<RemoteView> cjView) : cjView_(std::move(cjView))
31 {
32     LOGD("Native View constructed: %{public}" PRId64 ".", GetID());
33     useNewPipeline_ = Container::IsCurrentUseNewPipeline();
34     instanceId_ = Container::CurrentId();
35 }
36 
~NativeView()37 NativeView::~NativeView()
38 {
39     LOGD("Native View Destroyed: %{public}" PRId64 ".", GetID());
40 };
41 
GetDeletedElemtIds(std::vector<int64_t>& vec)42 void NativeView::GetDeletedElemtIds(std::vector<int64_t>& vec)
43 {
44     LOGD("NativeView, getting elmtIds of all deleted Elements from ElementRegister:");
45 }
46 
DeletedElmtIdsHaveBeenPurged(std::vector<int64_t>& vec)47 void NativeView::DeletedElmtIdsHaveBeenPurged(std::vector<int64_t>& vec)
48 {
49     LOGD("NativeView, getting elmtIds of all deleted Elements from ElementRegister:");
50 }
51 
CreateUI()52 RefPtr<AceType> NativeView::CreateUI()
53 {
54     wptr<NativeView> weakThis = this;
55     NodeInfoPU partialUpdateCallbacks {
56         .appearFunc = [weakThis]() -> void {
57             auto self = weakThis.promote();
58             CHECK_NULL_VOID(self);
59             ContainerScope scope(self->instanceId_);
60             self->cjView_->OnAppear();
61         },
62         .renderFunc = [weakThis]() -> RefPtr<AceType> {
63             auto self = weakThis.promote();
64             CHECK_NULL_RETURN(self, nullptr);
65             ContainerScope scope(self->instanceId_);
66             if (!self->isFirstRender_) {
67                 LOGW("the view has already called initial render");
68                 return nullptr;
69             }
70             self->isFirstRender_ = false;
71             return self->InitialUIRender();
72         },
73         .updateFunc = [weakThis]() -> void {
74             auto self = weakThis.promote();
75             CHECK_NULL_VOID(self);
76             ContainerScope scope(self->instanceId_);
77             if (!self->needsUpdate_) {
78                 LOGW("the view does not need to update");
79                 return;
80             }
81             self->needsUpdate_ = false;
82             self->cjView_->Rerender();
83             for (const UpdateTask& updateTask : self->pendingUpdateTasks_) {
84                 ViewPartialUpdateModel::GetInstance()->FlushUpdateTask(updateTask);
85             }
86             self->pendingUpdateTasks_.clear();
87         },
88         .removeFunc = [weakThis]() {
89             auto self = weakThis.promote();
90             CHECK_NULL_VOID(self);
91             self->Destroy();
92         },
93         .reloadFunc = [weakThis](bool deep) {
94             auto self = weakThis.promote();
95             CHECK_NULL_VOID(self);
96             ContainerScope scope(self->instanceId_);
97             self->cjView_->Reload(deep);
98         },
99         .completeReloadFunc = [weakThis]() -> RefPtr<AceType> {
100             auto view = weakThis.promote();
101             CHECK_NULL_RETURN(view, nullptr);
102             ContainerScope scope(view->instanceId_);
103             return view->InitialUIRender();
104         },
105     };
106     auto node = ViewPartialUpdateModel::GetInstance()->CreateNode(std::move(partialUpdateCallbacks));
107 
108     node_ = node;
109 
110     return node;
111 }
112 
InitialUIRender()113 RefPtr<AceType> NativeView::InitialUIRender()
114 {
115     needsUpdate_ = false;
116     {
117         cjView_->OnAboutToRender();
118     }
119     {
120         cjView_->Render();
121     }
122     {
123         cjView_->OnAfterRender();
124         if (onRenderDone_) {
125             onRenderDone_();
126         }
127     }
128     return ViewStackModel::GetInstance()->Finish();
129 }
130 
SyncInstanceId()131 void NativeView::SyncInstanceId()
132 {
133     restoreInstanceId_ = Container::CurrentId();
134     ContainerScope::UpdateCurrent(instanceId_);
135 }
136 
RestoreInstanceId()137 void NativeView::RestoreInstanceId()
138 {
139     ContainerScope::UpdateCurrent(restoreInstanceId_);
140 }
141 
142 /**
143  * marks the NativeView's composed component as needing update / rerender
144  */
MarkNeedUpdate()145 void NativeView::MarkNeedUpdate()
146 {
147     needsUpdate_ = ViewPartialUpdateModel::GetInstance()->MarkNeedUpdate(node_);
148 }
149 
FlushReload()150 void NativeView::FlushReload()
151 {
152     auto node = node_.Upgrade();
153     if (!node) {
154         LOGE("fail to update due to custom Node is null");
155         return;
156     }
157     if (AceType::InstanceOf<NG::CustomNode>(node)) {
158         auto customNode = AceType::DynamicCast<NG::CustomNode>(node);
159         customNode->FlushReload();
160     }
161 }
162 
FinishUpdateFunc(int32_t elmtId)163 void NativeView::FinishUpdateFunc(int32_t elmtId)
164 {
165     wptr<NativeView> weakThis = this;
166     ViewPartialUpdateModel::GetInstance()->FinishUpdate(node_, elmtId, [weakThis](const UpdateTask& task) {
167         auto cjView = weakThis.promote();
168         if (cjView) {
169             cjView->pendingUpdateTasks_.push_back(task);
170         }
171     });
172 }
173 
Destroy()174 void NativeView::Destroy()
175 {
176     if (!cjView_) {
177         LOGE("NativeView::Destroy error, nativeId: %{public}" PRId64 " cj view not exist.", GetID());
178         return;
179     }
180     LOGD("NativeView::Destroy start, nativeId: %{public}" PRId64 ", cjId: %{public}" PRId64, GetID(), cjView_->GetID());
181     {
182         cjView_->OnDisappear();
183     }
184     {
185         cjView_->OnAboutToBeDeleted();
186     }
187     pendingUpdateTasks_.clear();
188     LOGD("NativeView::Destroy end");
189 }
190 
Create(const sptr<NativeView>& view)191 void NativeView::Create(const sptr<NativeView>& view)
192 {
193     ViewStackModel::GetInstance()->Push(view->CreateUI(), true);
194 }
195 
CleanUpAbandonedChild()196 void NativeView::CleanUpAbandonedChild()
197 {
198     LOGD("NativeView::CleanUpAbandonedChild");
199 }
200 
FireOnShow()201 void NativeView::FireOnShow()
202 {
203     if (!cjView_) {
204         LOGE("NativeView::FireOnShow fail, no cj view on %{public}" PRId64 ".", GetID());
205         return;
206     }
207     {
208         cjView_->OnShow();
209     }
210 }
211 
FireOnHide()212 void NativeView::FireOnHide()
213 {
214     if (!cjView_) {
215         LOGE("NativeView::FireOnHide fail, no cj view on %{public}" PRId64 ".", GetID());
216         return;
217     }
218     {
219         cjView_->OnHide();
220     }
221 }
222 
FireOnBackPress()223 bool NativeView::FireOnBackPress()
224 {
225     if (!cjView_) {
226         LOGE("NativeView::FireOnBackPress fail, no cj view on %{public}" PRId64 ".", GetID());
227         return false;
228     }
229     {
230         return cjView_->OnBackPress();
231     }
232 }
233 
FireOnTransition()234 void NativeView::FireOnTransition()
235 {
236     if (!cjView_) {
237         LOGE("NativeView::FireOnTransition fail, no cj view on %{public}" PRId64 ".", GetID());
238         return;
239     }
240     cjView_->OnTransition();
241 }
242 
ExecuteUpdateWithValueParams(const std::string& jsonData)243 void NativeView::ExecuteUpdateWithValueParams(const std::string& jsonData)
244 {
245     if (!cjView_) {
246         LOGE("NativeView::ExecuteUpdateWithValueParams fail, no cj view on %{public}" PRId64 ".", GetID());
247         return;
248     }
249     cjView_->UpdateWithJson(jsonData);
250 }
251 
Reload(bool deep)252 void RemoteView::Reload(bool deep)
253 {
254     auto forceCompleteRerenderFunc =
255         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewForceCompleteRerender;
256     if (!forceCompleteRerenderFunc) {
257         LOGE("CJFunc: RemoteView::ForceCompleteRerender is empty.");
258         return;
259     }
260     forceCompleteRerenderFunc(GetID(), deep);
261 }
262 
VoidCallback(void (*cjFunc)(int64_t), const char* funcName)263 void RemoteView::VoidCallback(void (*cjFunc)(int64_t), const char* funcName)
264 {
265     if (!cjFunc) {
266         LOGE("CJFunc: RemoteView::%{public}s is empty.", funcName);
267         return;
268     }
269     cjFunc(GetID());
270 }
271 
Render()272 void RemoteView::Render()
273 {
274     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewRender, "Render");
275 }
276 
Rerender()277 void RemoteView::Rerender()
278 {
279     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewRerender, "Rerender");
280 }
281 
OnShow()282 void RemoteView::OnShow()
283 {
284     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnShow, "OnShow");
285 }
286 
OnHide()287 void RemoteView::OnHide()
288 {
289     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnHide, "OnHide");
290 }
291 
OnBackPress()292 bool RemoteView::OnBackPress()
293 {
294     auto onBackPressFunc = CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnBackPress;
295     if (!onBackPressFunc) {
296         LOGE("CJFunc: RemoteView::OnBackPress is empty.");
297         return false;
298     }
299     return onBackPressFunc(GetID());
300 }
301 
UpdateWithJson(const std::string& value)302 void RemoteView::UpdateWithJson(const std::string& value)
303 {
304     auto updateWithJsonFunc =
305         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewUpdateWithJson;
306     if (!updateWithJsonFunc) {
307         LOGE("CJFunc: RemoteView::UpdateWithJson is empty.");
308         return;
309     }
310     updateWithJsonFunc(GetID(), value.c_str());
311 }
312 
OnAppear()313 void RemoteView::OnAppear()
314 {
315     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAppear, "OnAppear");
316 }
317 
OnTransition()318 void RemoteView::OnTransition()
319 {
320     VoidCallback(
321         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnTransition, "OnTransition");
322 }
323 
OnAboutToRender()324 void RemoteView::OnAboutToRender()
325 {
326     VoidCallback(
327         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAboutToRender, "OnAboutToRender");
328 }
329 
OnAboutToBeDeleted()330 void RemoteView::OnAboutToBeDeleted()
331 {
332     VoidCallback(CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAboutToBeDeleted,
333         "OnAboutToBeDeleted");
334 }
335 
OnAfterRender()336 void RemoteView::OnAfterRender()
337 {
338     VoidCallback(
339         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnAfterRender, "OnAfterRender");
340 }
341 
OnDisappear()342 void RemoteView::OnDisappear()
343 {
344     VoidCallback(
345         CJRuntimeDelegate::GetInstance()->GetCJFuncs().atCOHOSAceFrameworkRemoteViewOnDisappear, "OnDisappear");
346 }
347 
348 } // namespace OHOS::Ace::Framework
349