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 "ui_observer.h"
17
18 #include "bridge/common/utils/engine_helper.h"
19 #include "core/components_ng/base/node_render_status_monitor.h"
20
21 namespace OHOS::Ace::Napi {
22 std::list<std::shared_ptr<UIObserverListener>> UIObserver::unspecifiedNavigationListeners_;
23 std::unordered_map<std::string, std::list<std::shared_ptr<UIObserverListener>>>
24 UIObserver::specifiedCNavigationListeners_;
25 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
26 UIObserver::specifiedUniqueIdNavigationListeners_;
27
28 std::list<std::shared_ptr<UIObserverListener>> UIObserver::scrollEventListeners_;
29 std::unordered_map<std::string, std::list<std::shared_ptr<UIObserverListener>>>
30 UIObserver::specifiedScrollEventListeners_;
31
32 std::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
33 UIObserver::abilityContextRouterPageListeners_;
34 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
35 UIObserver::specifiedRouterPageListeners_;
36 std::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::infosForRouterPage_;
37
38 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
39 UIObserver::specifiedDensityListeners_;
40 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>> UIObserver::specifiedDrawListeners_;
41 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>> UIObserver::specifiedLayoutListeners_;
42
43 std::unordered_map<napi_ref, UIObserver::NavIdAndListenersMap> UIObserver::abilityUIContextNavDesSwitchListeners_;
44 std::unordered_map<int32_t, UIObserver::NavIdAndListenersMap> UIObserver::uiContextNavDesSwitchListeners_;
45 std::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::infosForNavDesSwitch_;
46
47 std::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
48 UIObserver::abilityContextWillClickListeners_;
49 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
50 UIObserver::specifiedWillClickListeners_;
51 std::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::willClickInfos_;
52
53 std::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
54 UIObserver::abilityContextDidClickListeners_;
55 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
56 UIObserver::specifiedDidClickListeners_;
57 std::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::didClickInfos_;
58
59 std::list<std::shared_ptr<UIObserverListener>> UIObserver::tabContentStateListeners_;
60 std::unordered_map<std::string, std::list<std::shared_ptr<UIObserverListener>>>
61 UIObserver::specifiedTabContentStateListeners_;
62
63 std::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
64 UIObserver::abilityContextBeforePanStartListeners_;
65 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
66 UIObserver::specifiedBeforePanStartListeners_;
67 std::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::beforePanStartInfos_;
68 std::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
69 UIObserver::abilityContextBeforePanEndListeners_;
70 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
71 UIObserver::specifiedBeforePanEndListeners_;
72 std::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::beforePanEndInfos_;
73
74 std::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
75 UIObserver::abilityContextAfterPanStartListeners_;
76 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
77 UIObserver::specifiedAfterPanStartListeners_;
78 std::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::afterPanStartInfos_;
79 std::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
80 UIObserver::abilityContextAfterPanEndListeners_;
81 std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
82 UIObserver::specifiedAfterPanEndListeners_;
83 std::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::afterPanEndInfos_;
84 std::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::PanGestureInfos_;
85
86 std::unordered_map<NG::FrameNode*, std::shared_ptr<UIObserver::NodeRenderListener>>
87 UIObserver::specifiedNodeRenderStateListeners_;
88
89 template<typename ListenerList, typename... Args>
SafeIterateListeners(const ListenerList & listeners,void (UIObserverListener::* callback)(Args...),Args...args)90 void SafeIterateListeners(const ListenerList& listeners, void (UIObserverListener::*callback)(Args...), Args... args)
91 {
92 ListenerList listenersCopy = listeners;
93 for (const auto& listener : listenersCopy) {
94 (listener.get()->*callback)(std::forward<Args>(args)...);
95 }
96 }
97
98 // register a global listener without options
RegisterNavigationCallback(const std::shared_ptr<UIObserverListener> & listener)99 void UIObserver::RegisterNavigationCallback(const std::shared_ptr<UIObserverListener>& listener)
100 {
101 if (std::find(unspecifiedNavigationListeners_.begin(), unspecifiedNavigationListeners_.end(), listener) !=
102 unspecifiedNavigationListeners_.end()) {
103 return;
104 }
105 unspecifiedNavigationListeners_.emplace_back(listener);
106 }
107
108 // UIObserver.on(type: "navDestinationUpdate", options, callback)
109 // register a listener on a specified Navigation
RegisterNavigationCallback(std::string navigationId,const std::shared_ptr<UIObserverListener> & listener)110 void UIObserver::RegisterNavigationCallback(
111 std::string navigationId, const std::shared_ptr<UIObserverListener>& listener)
112 {
113 auto iter = specifiedCNavigationListeners_.find(navigationId);
114 if (iter == specifiedCNavigationListeners_.end()) {
115 specifiedCNavigationListeners_.emplace(
116 navigationId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
117 return;
118 }
119 auto& holder = iter->second;
120 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
121 return;
122 }
123 holder.emplace_back(listener);
124 }
125
126 // UIObserver.on(type: "navDestinationUpdate", navigationUniqueId, callback)
127 // register a listener on a specified Navigation
RegisterNavigationCallback(int32_t navigationUniqueId,const std::shared_ptr<UIObserverListener> & listener)128 void UIObserver::RegisterNavigationCallback(
129 int32_t navigationUniqueId, const std::shared_ptr<UIObserverListener>& listener)
130 {
131 auto iter = specifiedUniqueIdNavigationListeners_.find(navigationUniqueId);
132 if (iter == specifiedUniqueIdNavigationListeners_.end()) {
133 specifiedUniqueIdNavigationListeners_.emplace(
134 navigationUniqueId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
135 return;
136 }
137 auto& holder = iter->second;
138 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
139 return;
140 }
141 holder.emplace_back(listener);
142 }
143
144 // UIObserver.off(type: "navDestinationUpdate", callback)
UnRegisterNavigationCallback(napi_value cb)145 void UIObserver::UnRegisterNavigationCallback(napi_value cb)
146 {
147 if (cb == nullptr) {
148 unspecifiedNavigationListeners_.clear();
149 return;
150 }
151
152 unspecifiedNavigationListeners_.erase(
153 std::remove_if(
154 unspecifiedNavigationListeners_.begin(),
155 unspecifiedNavigationListeners_.end(),
156 [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
157 return registeredListener->NapiEqual(cb);
158 }
159 ),
160 unspecifiedNavigationListeners_.end()
161 );
162 }
163
164 // UIObserver.off(type: "navDestinationUpdate", options, callback)
UnRegisterNavigationCallback(std::string navigationId,napi_value cb)165 void UIObserver::UnRegisterNavigationCallback(std::string navigationId, napi_value cb)
166 {
167 auto iter = specifiedCNavigationListeners_.find(navigationId);
168 if (iter == specifiedCNavigationListeners_.end()) {
169 return;
170 }
171 auto& holder = iter->second;
172 if (cb == nullptr) {
173 holder.clear();
174 return;
175 }
176 holder.erase(
177 std::remove_if(
178 holder.begin(),
179 holder.end(),
180 [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
181 return registeredListener->NapiEqual(cb);
182 }
183 ),
184 holder.end()
185 );
186 }
187
188 // UIObserver.off(type: "navDestinationUpdate", navigationUniqueId, callback)
UnRegisterNavigationCallback(int32_t navigationUniqueId,napi_value cb)189 void UIObserver::UnRegisterNavigationCallback(int32_t navigationUniqueId, napi_value cb)
190 {
191 auto iter = specifiedUniqueIdNavigationListeners_.find(navigationUniqueId);
192 if (iter == specifiedUniqueIdNavigationListeners_.end()) {
193 return;
194 }
195 auto& holder = iter->second;
196 if (cb == nullptr) {
197 holder.clear();
198 return;
199 }
200 holder.erase(
201 std::remove_if(
202 holder.begin(),
203 holder.end(),
204 [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
205 return registeredListener->NapiEqual(cb);
206 }
207 ),
208 holder.end()
209 );
210 }
211
HandleNavigationStateChange(const NG::NavDestinationInfo & info)212 void UIObserver::HandleNavigationStateChange(const NG::NavDestinationInfo& info)
213 {
214 auto unspecifiedHolder = unspecifiedNavigationListeners_;
215 for (const auto& listener : unspecifiedHolder) {
216 listener->OnNavigationStateChange(info);
217 }
218 auto iter = specifiedCNavigationListeners_.find(info.navigationId);
219 if (iter != specifiedCNavigationListeners_.end()) {
220 auto holder = iter->second;
221
222 for (const auto& listener : holder) {
223 listener->OnNavigationStateChange(info);
224 }
225 }
226
227 auto navigationdUniqueIdIter = specifiedUniqueIdNavigationListeners_.find(info.navigationUniqueId);
228 if (navigationdUniqueIdIter != specifiedUniqueIdNavigationListeners_.end()) {
229 auto holder = navigationdUniqueIdIter->second;
230
231 for (const auto& listener : holder) {
232 listener->OnNavigationStateChange(info);
233 }
234 }
235 }
236
237 // UIObserver.on(type: "scrollEvent", callback)
238 // register a global listener without options
RegisterScrollEventCallback(const std::shared_ptr<UIObserverListener> & listener)239 void UIObserver::RegisterScrollEventCallback(const std::shared_ptr<UIObserverListener>& listener)
240 {
241 if (std::find(scrollEventListeners_.begin(), scrollEventListeners_.end(), listener) !=
242 scrollEventListeners_.end()) {
243 return;
244 }
245 scrollEventListeners_.emplace_back(listener);
246 }
247
248 // UIObserver.on(type: "scrollEvent", options, callback)
249 // register a listener on a specified scrollEvent
RegisterScrollEventCallback(const std::string & id,const std::shared_ptr<UIObserverListener> & listener)250 void UIObserver::RegisterScrollEventCallback(
251 const std::string& id, const std::shared_ptr<UIObserverListener>& listener)
252 {
253 auto iter = specifiedScrollEventListeners_.find(id);
254 if (iter == specifiedScrollEventListeners_.end()) {
255 specifiedScrollEventListeners_.emplace(id, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
256 return;
257 }
258 auto& holder = iter->second;
259 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
260 return;
261 }
262 holder.emplace_back(listener);
263 }
264
265 // UIObserver.off(type: "scrollEvent", callback)
UnRegisterScrollEventCallback(napi_value cb)266 void UIObserver::UnRegisterScrollEventCallback(napi_value cb)
267 {
268 if (cb == nullptr) {
269 scrollEventListeners_.clear();
270 return;
271 }
272
273 scrollEventListeners_.erase(
274 std::remove_if(
275 scrollEventListeners_.begin(),
276 scrollEventListeners_.end(),
277 [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
278 return registeredListener->NapiEqual(cb);
279 }),
280 scrollEventListeners_.end()
281 );
282 }
283
284 // UIObserver.off(type: "scrollEvent", options, callback)
UnRegisterScrollEventCallback(const std::string & id,napi_value cb)285 void UIObserver::UnRegisterScrollEventCallback(const std::string& id, napi_value cb)
286 {
287 auto iter = specifiedScrollEventListeners_.find(id);
288 if (iter == specifiedScrollEventListeners_.end()) {
289 return;
290 }
291 auto& holder = iter->second;
292 if (cb == nullptr) {
293 holder.clear();
294 return;
295 }
296 holder.erase(
297 std::remove_if(
298 holder.begin(),
299 holder.end(),
300 [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
301 return registeredListener->NapiEqual(cb);
302 }),
303 holder.end()
304 );
305 }
306
HandleScrollEventStateChange(const std::string & id,int32_t uniqueId,NG::ScrollEventType eventType,float offset,Ace::Axis axis)307 void UIObserver::HandleScrollEventStateChange(const std::string& id, int32_t uniqueId,
308 NG::ScrollEventType eventType, float offset, Ace::Axis axis)
309 {
310 // copy value to avoid developer call off while execute callback of on
311 auto scrollEventListeners = scrollEventListeners_;
312 for (const auto& listener : scrollEventListeners) {
313 listener->OnScrollEventStateChange(id, uniqueId, eventType, offset, axis);
314 }
315
316 auto iter = specifiedScrollEventListeners_.find(id);
317 if (iter == specifiedScrollEventListeners_.end()) {
318 return;
319 }
320
321 // copy value to avoid developer call off while execute callback of on
322 auto holder = iter->second;
323
324 for (const auto& listener : holder) {
325 listener->OnScrollEventStateChange(id, uniqueId, eventType, offset, axis);
326 }
327 }
328
329 // UIObserver.on(type: "routerPageUpdate", UIAbilityContext, callback)
330 // register a listener on current page
RegisterRouterPageCallback(napi_env env,napi_value uiAbilityContext,const std::shared_ptr<UIObserverListener> & listener)331 void UIObserver::RegisterRouterPageCallback(
332 napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
333 {
334 NG::AbilityContextInfo info;
335 GetAbilityInfos(env, uiAbilityContext, info);
336 for (auto listenerPair : abilityContextRouterPageListeners_) {
337 auto ref = listenerPair.first;
338 auto localInfo = infosForRouterPage_[ref];
339 if (info.IsEqual(localInfo)) {
340 auto& holder = abilityContextRouterPageListeners_[ref];
341 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
342 return;
343 }
344 holder.emplace_back(listener);
345 return;
346 }
347 }
348 napi_ref newRef = nullptr;
349 napi_create_reference(env, uiAbilityContext, 1, &newRef);
350 abilityContextRouterPageListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
351 infosForRouterPage_[newRef] = info;
352 }
353
354 // UIObserver.on(type: "routerPageUpdate", uiContext | null, callback)
355 // register a listener on current page
RegisterRouterPageCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)356 void UIObserver::RegisterRouterPageCallback(
357 int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
358 {
359 if (uiContextInstanceId == 0) {
360 uiContextInstanceId = Container::CurrentId();
361 }
362 auto iter = specifiedRouterPageListeners_.find(uiContextInstanceId);
363 if (iter == specifiedRouterPageListeners_.end()) {
364 specifiedRouterPageListeners_.emplace(
365 uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
366 return;
367 }
368 auto& holder = iter->second;
369 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
370 return;
371 }
372 holder.emplace_back(listener);
373 }
374
375 // UIObserver.off(type: "routerPageUpdate", uiAbilityContext, callback)
UnRegisterRouterPageCallback(napi_env env,napi_value uiAbilityContext,napi_value callback)376 void UIObserver::UnRegisterRouterPageCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
377 {
378 NG::AbilityContextInfo info;
379 GetAbilityInfos(env, uiAbilityContext, info);
380 for (auto listenerPair : abilityContextRouterPageListeners_) {
381 auto ref = listenerPair.first;
382 auto localInfo = infosForRouterPage_[ref];
383 if (info.IsEqual(localInfo)) {
384 auto& holder = abilityContextRouterPageListeners_[listenerPair.first];
385 if (callback == nullptr) {
386 holder.clear();
387 } else {
388 holder.erase(
389 std::remove_if(
390 holder.begin(),
391 holder.end(),
392 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
393 return registeredListener->NapiEqual(callback);
394 }),
395 holder.end());
396 }
397 if (holder.empty()) {
398 infosForRouterPage_.erase(ref);
399 abilityContextRouterPageListeners_.erase(ref);
400 napi_delete_reference(env, ref);
401 }
402 return;
403 }
404 }
405 }
406
407 // UIObserver.off(type: "routerPageUpdate", uiContext | null, callback)
UnRegisterRouterPageCallback(int32_t uiContextInstanceId,napi_value callback)408 void UIObserver::UnRegisterRouterPageCallback(int32_t uiContextInstanceId, napi_value callback)
409 {
410 if (uiContextInstanceId == 0) {
411 uiContextInstanceId = Container::CurrentId();
412 }
413 auto iter = specifiedRouterPageListeners_.find(uiContextInstanceId);
414 if (iter == specifiedRouterPageListeners_.end()) {
415 return;
416 }
417 auto& holder = iter->second;
418 if (callback == nullptr) {
419 holder.clear();
420 return;
421 }
422 holder.erase(
423 std::remove_if(
424 holder.begin(),
425 holder.end(),
426 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
427 return registeredListener->NapiEqual(callback);
428 }),
429 holder.end());
430 }
431
432 // UIObserver.on(type: "willDraw", uiContext | null, callback)
433 // register a listener on current page
RegisterDrawCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)434 void UIObserver::RegisterDrawCallback(int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
435 {
436 if (uiContextInstanceId == 0) {
437 uiContextInstanceId = Container::CurrentId();
438 }
439 if (specifiedDrawListeners_.find(uiContextInstanceId) == specifiedDrawListeners_.end()) {
440 specifiedDrawListeners_[uiContextInstanceId] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
441 return;
442 }
443 auto& holder = specifiedDrawListeners_[uiContextInstanceId];
444 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
445 return;
446 }
447 holder.emplace_back(listener);
448 }
449
450 // UIObserver.off(type: "willDraw", uiContext | null, callback)
UnRegisterDrawCallback(int32_t uiContextInstanceId,napi_value callback)451 void UIObserver::UnRegisterDrawCallback(int32_t uiContextInstanceId, napi_value callback)
452 {
453 if (uiContextInstanceId == 0) {
454 uiContextInstanceId = Container::CurrentId();
455 }
456 if (specifiedDrawListeners_.find(uiContextInstanceId) == specifiedDrawListeners_.end()) {
457 return;
458 }
459 auto& holder = specifiedDrawListeners_[uiContextInstanceId];
460 if (callback == nullptr) {
461 auto container = Container::GetContainer(uiContextInstanceId);
462 CHECK_NULL_VOID(container);
463 auto taskExecutor = container->GetTaskExecutor();
464 CHECK_NULL_VOID(taskExecutor);
465 taskExecutor->PostTask([&holder]() { holder.clear(); }, TaskExecutor::TaskType::UI, "ArkUIClearListener");
466 return;
467 }
468 holder.erase(
469 std::remove_if(
470 holder.begin(),
471 holder.end(),
472 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
473 return registeredListener->NapiEqual(callback);
474 }),
475 holder.end());
476 }
477
478 // UIObserver.on(type: "didLayout", uiContext | null, callback)
479 // register a listener on current page
RegisterLayoutCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)480 void UIObserver::RegisterLayoutCallback(
481 int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
482 {
483 if (uiContextInstanceId == 0) {
484 uiContextInstanceId = Container::CurrentId();
485 }
486 if (specifiedLayoutListeners_.find(uiContextInstanceId) == specifiedLayoutListeners_.end()) {
487 specifiedLayoutListeners_[uiContextInstanceId] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
488 return;
489 }
490 auto& holder = specifiedLayoutListeners_[uiContextInstanceId];
491 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
492 return;
493 }
494 holder.emplace_back(listener);
495 }
496
497 // UIObserver.off(type: "didLayout", uiContext | null, callback)
UnRegisterLayoutCallback(int32_t uiContextInstanceId,napi_value callback)498 void UIObserver::UnRegisterLayoutCallback(int32_t uiContextInstanceId, napi_value callback)
499 {
500 if (uiContextInstanceId == 0) {
501 uiContextInstanceId = Container::CurrentId();
502 }
503 if (specifiedLayoutListeners_.find(uiContextInstanceId) == specifiedLayoutListeners_.end()) {
504 return;
505 }
506 auto& holder = specifiedLayoutListeners_[uiContextInstanceId];
507 if (callback == nullptr) {
508 auto container = Container::GetContainer(uiContextInstanceId);
509 CHECK_NULL_VOID(container);
510 auto taskExecutor = container->GetTaskExecutor();
511 CHECK_NULL_VOID(taskExecutor);
512 taskExecutor->PostTask([&holder]() { holder.clear(); }, TaskExecutor::TaskType::UI, "ArkUIClearListener");
513 return;
514 }
515 holder.erase(
516 std::remove_if(
517 holder.begin(),
518 holder.end(),
519 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
520 return registeredListener->NapiEqual(callback);
521 }),
522 holder.end());
523 }
524
HandleRouterPageStateChange(NG::AbilityContextInfo & info,const NG::RouterPageInfoNG & pageInfo)525 void UIObserver::HandleRouterPageStateChange(NG::AbilityContextInfo& info, const NG::RouterPageInfoNG& pageInfo)
526 {
527 for (auto listenerPair : abilityContextRouterPageListeners_) {
528 auto ref = listenerPair.first;
529 auto localInfo = infosForRouterPage_[ref];
530 if (info.IsEqual(localInfo)) {
531 auto env = GetCurrentNapiEnv();
532 napi_value abilityContext = nullptr;
533 napi_get_reference_value(env, ref, &abilityContext);
534
535 NG::RouterPageInfoNG abilityPageInfo(
536 abilityContext, pageInfo.index, pageInfo.name, pageInfo.path, pageInfo.state, pageInfo.pageId);
537 auto holder = abilityContextRouterPageListeners_[ref];
538 for (const auto& listener : holder) {
539 listener->OnRouterPageStateChange(abilityPageInfo);
540 }
541 break;
542 }
543 }
544
545 auto currentId = Container::CurrentId();
546 auto iter = specifiedRouterPageListeners_.find(currentId);
547 if (iter == specifiedRouterPageListeners_.end()) {
548 return;
549 }
550 auto holder = iter->second;
551 for (const auto& listener : holder) {
552 listener->OnRouterPageStateChange(pageInfo);
553 }
554 }
555
556 // UIObserver.on(type: "densityUpdate", uiContext | null, callback)
557 // register a listener on current page
RegisterDensityCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)558 void UIObserver::RegisterDensityCallback(
559 int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
560 {
561 if (uiContextInstanceId == 0) {
562 uiContextInstanceId = Container::CurrentId();
563 }
564 auto iter = specifiedDensityListeners_.find(uiContextInstanceId);
565 if (iter == specifiedDensityListeners_.end()) {
566 specifiedDensityListeners_.emplace(
567 uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
568 return;
569 }
570 auto& holder = iter->second;
571 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
572 return;
573 }
574 holder.emplace_back(listener);
575 }
576
577 // UIObserver.off(type: "densityUpdate", uiContext | null, callback)
UnRegisterDensityCallback(int32_t uiContextInstanceId,napi_value callback)578 void UIObserver::UnRegisterDensityCallback(int32_t uiContextInstanceId, napi_value callback)
579 {
580 if (uiContextInstanceId == 0) {
581 uiContextInstanceId = Container::CurrentId();
582 }
583 auto iter = specifiedDensityListeners_.find(uiContextInstanceId);
584 if (iter == specifiedDensityListeners_.end()) {
585 return;
586 }
587 auto& holder = iter->second;
588 if (callback == nullptr) {
589 holder.clear();
590 return;
591 }
592 holder.erase(
593 std::remove_if(
594 holder.begin(),
595 holder.end(),
596 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
597 return registeredListener->NapiEqual(callback);
598 }),
599 holder.end());
600 }
601
HandleDensityChange(NG::AbilityContextInfo & info,double density)602 void UIObserver::HandleDensityChange(NG::AbilityContextInfo& info, double density)
603 {
604 auto currentId = Container::CurrentId();
605 auto iter = specifiedDensityListeners_.find(currentId);
606 if (iter == specifiedDensityListeners_.end()) {
607 return;
608 }
609 SafeIterateListeners(iter->second, &UIObserverListener::OnDensityChange, density);
610 }
611
HandDrawCommandSendChange()612 void UIObserver::HandDrawCommandSendChange()
613 {
614 auto currentId = Container::CurrentId();
615 if (specifiedDrawListeners_.find(currentId) == specifiedDrawListeners_.end()) {
616 return;
617 }
618 SafeIterateListeners(specifiedDrawListeners_[currentId], &UIObserverListener::OnDrawOrLayout);
619 }
620
HandLayoutDoneChange()621 void UIObserver::HandLayoutDoneChange()
622 {
623 auto currentId = Container::CurrentId();
624 if (specifiedLayoutListeners_.find(currentId) == specifiedLayoutListeners_.end()) {
625 return;
626 }
627 SafeIterateListeners(specifiedLayoutListeners_[currentId], &UIObserverListener::OnDrawOrLayout);
628 }
629
630 /**
631 * observer.on('navDestinationSwitch', context: UIAbilityContext, callback)
632 * observer.on('navDestinationSwitch', context: UIAbilityContext, { navigationId: navId }, callback)
633 */
RegisterNavDestinationSwitchCallback(napi_env env,napi_value uiAbilityContext,const std::optional<std::string> & navigationId,const std::shared_ptr<UIObserverListener> & listener)634 void UIObserver::RegisterNavDestinationSwitchCallback(napi_env env, napi_value uiAbilityContext,
635 const std::optional<std::string>& navigationId, const std::shared_ptr<UIObserverListener>& listener)
636 {
637 NG::AbilityContextInfo info;
638 GetAbilityInfos(env, uiAbilityContext, info);
639 for (auto& listenerPair : abilityUIContextNavDesSwitchListeners_) {
640 auto ref = listenerPair.first;
641 auto localInfo = infosForNavDesSwitch_[ref];
642 if (!info.IsEqual(localInfo)) {
643 continue;
644 }
645
646 auto& listenersMap = listenerPair.second;
647 auto it = listenersMap.find(navigationId);
648 if (it == listenersMap.end()) {
649 listenersMap[navigationId] = std::list<std::shared_ptr<UIObserverListener>>({listener});
650 return;
651 }
652 if (std::find(it->second.begin(), it->second.end(), listener) == it->second.end()) {
653 it->second.emplace_back(listener);
654 }
655 return;
656 }
657 napi_ref newRef = nullptr;
658 napi_create_reference(env, uiAbilityContext, 1, &newRef);
659 NavIdAndListenersMap listenersMap;
660 listenersMap.emplace(navigationId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
661 abilityUIContextNavDesSwitchListeners_[newRef] = listenersMap;
662 infosForNavDesSwitch_[newRef] = info;
663 }
664
665 /**
666 * UIObserver.on('navDestinationSwitch', { navigationId: navId }, callback)
667 * UIObserver.on('navDestinationSwitch', callback)
668 * observer.on('navDestinationSwitch', context: UIContext, { navigationId?: navId }, callback)
669 */
RegisterNavDestinationSwitchCallback(int32_t uiContextInstanceId,const std::optional<std::string> & navigationId,const std::shared_ptr<UIObserverListener> & listener)670 void UIObserver::RegisterNavDestinationSwitchCallback(int32_t uiContextInstanceId,
671 const std::optional<std::string>& navigationId, const std::shared_ptr<UIObserverListener>& listener)
672 {
673 if (uiContextInstanceId == 0) {
674 uiContextInstanceId = Container::CurrentId();
675 }
676 auto listenersMapIter = uiContextNavDesSwitchListeners_.find(uiContextInstanceId);
677 if (listenersMapIter == uiContextNavDesSwitchListeners_.end()) {
678 NavIdAndListenersMap listenersMap;
679 listenersMap.emplace(navigationId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
680 uiContextNavDesSwitchListeners_[uiContextInstanceId] = listenersMap;
681 return;
682 }
683
684 auto& listenersMap = listenersMapIter->second;
685 auto it = listenersMap.find(navigationId);
686 if (it == listenersMap.end()) {
687 listenersMap[navigationId] = std::list<std::shared_ptr<UIObserverListener>>({listener});
688 return;
689 }
690
691 if (std::find(it->second.begin(), it->second.end(), listener) == it->second.end()) {
692 it->second.emplace_back(listener);
693 }
694 }
695
696 /**
697 * observer.off('navDestinationSwitch', context: AbilityUIContext})
698 * observer.off('navDestinationSwitch', context: AbilityUIContext, callback })
699 * observer.off('navDestinationSwitch', context: AbilityUIContext, { navigationId: navId } })
700 * observer.off('navDestinationSwitch', context: AbilityUIContext, { navigationId: navId }, callback })
701 */
UnRegisterNavDestinationSwitchCallback(napi_env env,napi_value uiAbilityContext,const std::optional<std::string> & navigationId,napi_value callback)702 void UIObserver::UnRegisterNavDestinationSwitchCallback(napi_env env, napi_value uiAbilityContext,
703 const std::optional<std::string>& navigationId, napi_value callback)
704 {
705 NG::AbilityContextInfo info;
706 GetAbilityInfos(env, uiAbilityContext, info);
707 for (auto listenerPair : abilityUIContextNavDesSwitchListeners_) {
708 auto ref = listenerPair.first;
709 auto localInfo = infosForNavDesSwitch_[ref];
710 if (!info.IsEqual(localInfo)) {
711 continue;
712 }
713
714 auto& listenersMap = listenerPair.second;
715 auto it = listenersMap.find(navigationId);
716 if (it == listenersMap.end()) {
717 return;
718 }
719 auto& listeners = it->second;
720 if (callback == nullptr) {
721 listeners.clear();
722 } else {
723 listeners.erase(std::remove_if(listeners.begin(), listeners.end(),
724 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
725 return registeredListener->NapiEqual(callback);
726 }), listeners.end());
727 }
728 if (listeners.empty()) {
729 listenersMap.erase(it);
730 }
731 if (listenersMap.empty()) {
732 infosForNavDesSwitch_.erase(ref);
733 abilityUIContextNavDesSwitchListeners_.erase(ref);
734 napi_delete_reference(env, ref);
735 }
736 return;
737 }
738 }
739
740 /**
741 * observer.off('navDestinationSwitch', context: UIContext})
742 * observer.off('navDestinationSwitch', context: UIContext, callback })
743 * observer.off('navDestinationSwitch', context: UIContext, { navigationId: navId })
744 * observer.off('navDestinationSwitch', context: UIContext, { navigationId: navId }, callback )
745 * UIObserver.off('navDestinationSwitch')
746 * UIObserver.off('navDestinationSwitch', callback)
747 * UIObserver.off('navDestinationSwitch', { navigationId: navId })
748 * UIObserver.off('navDestinationSwitch', { navigationId: navId }, callback )
749 */
UnRegisterNavDestinationSwitchCallback(int32_t uiContextInstanceId,const std::optional<std::string> & navigationId,napi_value callback)750 void UIObserver::UnRegisterNavDestinationSwitchCallback(int32_t uiContextInstanceId,
751 const std::optional<std::string>& navigationId, napi_value callback)
752 {
753 if (uiContextInstanceId == 0) {
754 uiContextInstanceId = Container::CurrentId();
755 }
756 auto listenersMapIter = uiContextNavDesSwitchListeners_.find(uiContextInstanceId);
757 if (listenersMapIter == uiContextNavDesSwitchListeners_.end()) {
758 return;
759 }
760 auto& listenersMap = listenersMapIter->second;
761 auto it = listenersMap.find(navigationId);
762 if (it == listenersMap.end()) {
763 return;
764 }
765 auto& listeners = it->second;
766 if (callback == nullptr) {
767 listeners.clear();
768 } else {
769 listeners.erase(std::remove_if(listeners.begin(), listeners.end(),
770 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
771 return registeredListener->NapiEqual(callback);
772 }), listeners.end());
773 }
774 if (listeners.empty()) {
775 listenersMap.erase(it);
776 }
777 if (listenersMap.empty()) {
778 uiContextNavDesSwitchListeners_.erase(listenersMapIter);
779 }
780 }
781
HandleNavDestinationSwitch(const NG::AbilityContextInfo & info,NG::NavDestinationSwitchInfo & switchInfo)782 void UIObserver::HandleNavDestinationSwitch(
783 const NG::AbilityContextInfo& info, NG::NavDestinationSwitchInfo& switchInfo)
784 {
785 HandleAbilityUIContextNavDestinationSwitch(info, switchInfo);
786 HandleUIContextNavDestinationSwitch(switchInfo);
787 }
788
HandleAbilityUIContextNavDestinationSwitch(const NG::AbilityContextInfo & info,NG::NavDestinationSwitchInfo & switchInfo)789 void UIObserver::HandleAbilityUIContextNavDestinationSwitch(
790 const NG::AbilityContextInfo& info, NG::NavDestinationSwitchInfo& switchInfo)
791 {
792 napi_value uiContextBackup = switchInfo.context;
793 for (auto listenerPair : abilityUIContextNavDesSwitchListeners_) {
794 auto ref = listenerPair.first;
795 auto localInfo = infosForNavDesSwitch_[ref];
796 if (!info.IsEqual(localInfo)) {
797 continue;
798 }
799
800 auto env = GetCurrentNapiEnv();
801 napi_value abilityContext = nullptr;
802 napi_get_reference_value(env, ref, &abilityContext);
803
804 switchInfo.context = abilityContext;
805 auto listenersMap = listenerPair.second;
806 HandleListenersWithEmptyNavigationId(listenersMap, switchInfo);
807 HandleListenersWithSpecifiedNavigationId(listenersMap, switchInfo);
808 break;
809 }
810 switchInfo.context = uiContextBackup;
811 }
812
HandleUIContextNavDestinationSwitch(const NG::NavDestinationSwitchInfo & switchInfo)813 void UIObserver::HandleUIContextNavDestinationSwitch(const NG::NavDestinationSwitchInfo& switchInfo)
814 {
815 auto currentId = Container::CurrentId();
816 auto listenersMapIter = uiContextNavDesSwitchListeners_.find(currentId);
817 if (listenersMapIter == uiContextNavDesSwitchListeners_.end()) {
818 return;
819 }
820 auto listenersMap = listenersMapIter->second;
821 HandleListenersWithEmptyNavigationId(listenersMap, switchInfo);
822 HandleListenersWithSpecifiedNavigationId(listenersMap, switchInfo);
823 }
824
HandleListenersWithEmptyNavigationId(const NavIdAndListenersMap & listenersMap,const NG::NavDestinationSwitchInfo & switchInfo)825 void UIObserver::HandleListenersWithEmptyNavigationId(
826 const NavIdAndListenersMap& listenersMap, const NG::NavDestinationSwitchInfo& switchInfo)
827 {
828 std::optional<std::string> navId;
829 auto it = listenersMap.find(navId);
830 if (it != listenersMap.end()) {
831 const auto listeners = it->second;
832 for (const auto& listener : listeners) {
833 listener->OnNavDestinationSwitch(switchInfo);
834 }
835 }
836 }
837
HandleListenersWithSpecifiedNavigationId(const NavIdAndListenersMap & listenersMap,const NG::NavDestinationSwitchInfo & switchInfo)838 void UIObserver::HandleListenersWithSpecifiedNavigationId(
839 const NavIdAndListenersMap& listenersMap, const NG::NavDestinationSwitchInfo& switchInfo)
840 {
841 std::string navigationId;
842 if (switchInfo.from.has_value()) {
843 navigationId = switchInfo.from.value().navigationId;
844 } else if (switchInfo.to.has_value()) {
845 navigationId = switchInfo.to.value().navigationId;
846 }
847 if (!navigationId.empty()) {
848 std::optional<std::string> navId{navigationId};
849 auto it = listenersMap.find(navId);
850 if (it != listenersMap.end()) {
851 const auto listeners = it->second;
852 for (const auto& listener : listeners) {
853 listener->OnNavDestinationSwitch(switchInfo);
854 }
855 }
856 }
857 }
858
RegisterWillClickCallback(napi_env env,napi_value uiAbilityContext,const std::shared_ptr<UIObserverListener> & listener)859 void UIObserver::RegisterWillClickCallback(
860 napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
861 {
862 napi_handle_scope scope = nullptr;
863 auto status = napi_open_handle_scope(env, &scope);
864 if (status != napi_ok) {
865 return;
866 }
867 NG::AbilityContextInfo info;
868 GetAbilityInfos(env, uiAbilityContext, info);
869 for (auto listenerPair : abilityContextWillClickListeners_) {
870 auto ref = listenerPair.first;
871 auto localInfo = willClickInfos_[ref];
872 if (info.IsEqual(localInfo)) {
873 auto& holder = abilityContextWillClickListeners_[ref];
874 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
875 napi_close_handle_scope(env, scope);
876 return;
877 }
878 holder.emplace_back(listener);
879 napi_close_handle_scope(env, scope);
880 return;
881 }
882 }
883 napi_ref newRef = nullptr;
884 napi_create_reference(env, uiAbilityContext, 1, &newRef);
885 abilityContextWillClickListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
886 willClickInfos_[newRef] = info;
887 napi_close_handle_scope(env, scope);
888 }
889
RegisterWillClickCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)890 void UIObserver::RegisterWillClickCallback(
891 int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
892 {
893 if (uiContextInstanceId == 0) {
894 uiContextInstanceId = Container::CurrentId();
895 }
896 auto iter = specifiedWillClickListeners_.find(uiContextInstanceId);
897 if (iter == specifiedWillClickListeners_.end()) {
898 specifiedWillClickListeners_.emplace(
899 uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
900 return;
901 }
902 auto& holder = iter->second;
903 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
904 return;
905 }
906 holder.emplace_back(listener);
907 }
908
UnRegisterWillClickCallback(napi_env env,napi_value uiAbilityContext,napi_value callback)909 void UIObserver::UnRegisterWillClickCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
910 {
911 napi_handle_scope scope = nullptr;
912 auto status = napi_open_handle_scope(env, &scope);
913 if (status != napi_ok) {
914 return;
915 }
916 NG::AbilityContextInfo info;
917 GetAbilityInfos(env, uiAbilityContext, info);
918 for (auto listenerPair : abilityContextWillClickListeners_) {
919 auto ref = listenerPair.first;
920 auto localInfo = willClickInfos_[ref];
921 if (!info.IsEqual(localInfo)) {
922 continue;
923 }
924 auto& holder = abilityContextWillClickListeners_[listenerPair.first];
925 if (callback == nullptr) {
926 holder.clear();
927 } else {
928 holder.erase(
929 std::remove_if(
930 holder.begin(),
931 holder.end(),
932 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
933 return registeredListener->NapiEqual(callback);
934 }),
935 holder.end());
936 }
937 if (holder.empty()) {
938 willClickInfos_.erase(ref);
939 abilityContextWillClickListeners_.erase(ref);
940 napi_delete_reference(env, ref);
941 }
942 }
943 napi_close_handle_scope(env, scope);
944 }
945
UnRegisterWillClickCallback(int32_t uiContextInstanceId,napi_value callback)946 void UIObserver::UnRegisterWillClickCallback(int32_t uiContextInstanceId, napi_value callback)
947 {
948 if (uiContextInstanceId == 0) {
949 uiContextInstanceId = Container::CurrentId();
950 }
951 auto iter = specifiedWillClickListeners_.find(uiContextInstanceId);
952 if (iter == specifiedWillClickListeners_.end()) {
953 return;
954 }
955 auto& holder = iter->second;
956 if (callback == nullptr) {
957 holder.clear();
958 return;
959 }
960 holder.erase(
961 std::remove_if(
962 holder.begin(),
963 holder.end(),
964 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
965 return registeredListener->NapiEqual(callback);
966 }),
967 holder.end());
968 }
969
HandleWillClick(NG::AbilityContextInfo & info,const GestureEvent & gestureEventInfo,const ClickInfo & clickInfo,const RefPtr<NG::FrameNode> & frameNode)970 void UIObserver::HandleWillClick(NG::AbilityContextInfo& info, const GestureEvent& gestureEventInfo,
971 const ClickInfo& clickInfo, const RefPtr<NG::FrameNode>& frameNode)
972 {
973 auto env = GetCurrentNapiEnv();
974 napi_handle_scope scope = nullptr;
975 auto status = napi_open_handle_scope(env, &scope);
976 if (status != napi_ok) {
977 return;
978 }
979 for (auto listenerPair : abilityContextWillClickListeners_) {
980 auto ref = listenerPair.first;
981 auto localInfo = willClickInfos_[ref];
982 if (info.IsEqual(localInfo)) {
983 napi_value abilityContext = nullptr;
984 napi_get_reference_value(env, ref, &abilityContext);
985
986 auto& holder = abilityContextWillClickListeners_[ref];
987 for (const auto& listener : holder) {
988 listener->OnWillClick(gestureEventInfo, clickInfo, frameNode);
989 }
990 break;
991 }
992 }
993
994 auto currentId = Container::CurrentId();
995 auto iter = specifiedWillClickListeners_.find(currentId);
996 if (iter == specifiedWillClickListeners_.end()) {
997 napi_close_handle_scope(env, scope);
998 return;
999 }
1000 auto& holder = iter->second;
1001 for (const auto& listener : holder) {
1002 listener->OnWillClick(gestureEventInfo, clickInfo, frameNode);
1003 }
1004 napi_close_handle_scope(env, scope);
1005 }
1006
RegisterDidClickCallback(napi_env env,napi_value uiAbilityContext,const std::shared_ptr<UIObserverListener> & listener)1007 void UIObserver::RegisterDidClickCallback(
1008 napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
1009 {
1010 napi_handle_scope scope = nullptr;
1011 auto status = napi_open_handle_scope(env, &scope);
1012 if (status != napi_ok) {
1013 return;
1014 }
1015 NG::AbilityContextInfo info;
1016 GetAbilityInfos(env, uiAbilityContext, info);
1017 for (auto listenerPair : abilityContextDidClickListeners_) {
1018 auto ref = listenerPair.first;
1019 auto localInfo = didClickInfos_[ref];
1020 if (info.IsEqual(localInfo)) {
1021 auto& holder = abilityContextDidClickListeners_[ref];
1022 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1023 napi_close_handle_scope(env, scope);
1024 return;
1025 }
1026 holder.emplace_back(listener);
1027 napi_close_handle_scope(env, scope);
1028 return;
1029 }
1030 }
1031 napi_ref newRef = nullptr;
1032 napi_create_reference(env, uiAbilityContext, 1, &newRef);
1033 abilityContextDidClickListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
1034 didClickInfos_[newRef] = info;
1035 napi_close_handle_scope(env, scope);
1036 }
1037
RegisterDidClickCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)1038 void UIObserver::RegisterDidClickCallback(
1039 int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
1040 {
1041 if (uiContextInstanceId == 0) {
1042 uiContextInstanceId = Container::CurrentId();
1043 }
1044 auto iter = specifiedDidClickListeners_.find(uiContextInstanceId);
1045 if (iter == specifiedDidClickListeners_.end()) {
1046 specifiedDidClickListeners_.emplace(
1047 uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
1048 return;
1049 }
1050 auto& holder = iter->second;
1051 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1052 return;
1053 }
1054 holder.emplace_back(listener);
1055 }
1056
UnRegisterDidClickCallback(napi_env env,napi_value uiAbilityContext,napi_value callback)1057 void UIObserver::UnRegisterDidClickCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
1058 {
1059 napi_handle_scope scope = nullptr;
1060 auto status = napi_open_handle_scope(env, &scope);
1061 if (status != napi_ok) {
1062 return;
1063 }
1064 NG::AbilityContextInfo info;
1065 GetAbilityInfos(env, uiAbilityContext, info);
1066 for (auto listenerPair : abilityContextDidClickListeners_) {
1067 auto ref = listenerPair.first;
1068 auto localInfo = didClickInfos_[ref];
1069 if (!info.IsEqual(localInfo)) {
1070 continue;
1071 }
1072 auto& holder = abilityContextDidClickListeners_[listenerPair.first];
1073 if (callback == nullptr) {
1074 holder.clear();
1075 } else {
1076 holder.erase(
1077 std::remove_if(
1078 holder.begin(),
1079 holder.end(),
1080 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1081 return registeredListener->NapiEqual(callback);
1082 }),
1083 holder.end());
1084 }
1085 if (holder.empty()) {
1086 didClickInfos_.erase(ref);
1087 abilityContextDidClickListeners_.erase(ref);
1088 napi_delete_reference(env, ref);
1089 }
1090 }
1091 napi_close_handle_scope(env, scope);
1092 }
1093
UnRegisterDidClickCallback(int32_t uiContextInstanceId,napi_value callback)1094 void UIObserver::UnRegisterDidClickCallback(int32_t uiContextInstanceId, napi_value callback)
1095 {
1096 if (uiContextInstanceId == 0) {
1097 uiContextInstanceId = Container::CurrentId();
1098 }
1099 auto iter = specifiedDidClickListeners_.find(uiContextInstanceId);
1100 if (iter == specifiedDidClickListeners_.end()) {
1101 return;
1102 }
1103 auto& holder = iter->second;
1104 if (callback == nullptr) {
1105 holder.clear();
1106 return;
1107 }
1108 holder.erase(
1109 std::remove_if(
1110 holder.begin(),
1111 holder.end(),
1112 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1113 return registeredListener->NapiEqual(callback);
1114 }),
1115 holder.end());
1116 }
1117
HandleDidClick(NG::AbilityContextInfo & info,const GestureEvent & gestureEventInfo,const ClickInfo & clickInfo,const RefPtr<NG::FrameNode> & frameNode)1118 void UIObserver::HandleDidClick(NG::AbilityContextInfo& info, const GestureEvent& gestureEventInfo,
1119 const ClickInfo& clickInfo, const RefPtr<NG::FrameNode>& frameNode)
1120 {
1121 auto env = GetCurrentNapiEnv();
1122 napi_handle_scope scope = nullptr;
1123 auto status = napi_open_handle_scope(env, &scope);
1124 if (status != napi_ok) {
1125 return;
1126 }
1127 for (auto listenerPair : abilityContextDidClickListeners_) {
1128 auto ref = listenerPair.first;
1129 auto localInfo = didClickInfos_[ref];
1130 if (info.IsEqual(localInfo)) {
1131 napi_value abilityContext = nullptr;
1132 napi_get_reference_value(env, ref, &abilityContext);
1133
1134 auto& holder = abilityContextDidClickListeners_[ref];
1135 for (const auto& listener : holder) {
1136 listener->OnDidClick(gestureEventInfo, clickInfo, frameNode);
1137 }
1138 break;
1139 }
1140 }
1141
1142 auto currentId = Container::CurrentId();
1143 auto iter = specifiedDidClickListeners_.find(currentId);
1144 if (iter == specifiedDidClickListeners_.end()) {
1145 napi_close_handle_scope(env, scope);
1146 return;
1147 }
1148 auto& holder = iter->second;
1149 for (const auto& listener : holder) {
1150 listener->OnDidClick(gestureEventInfo, clickInfo, frameNode);
1151 }
1152 napi_close_handle_scope(env, scope);
1153 }
1154
RegisterBeforePanStartCallback(napi_env env,napi_value uiAbilityContext,const std::shared_ptr<UIObserverListener> & listener)1155 void UIObserver::RegisterBeforePanStartCallback(
1156 napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
1157 {
1158 napi_handle_scope scope = nullptr;
1159 auto status = napi_open_handle_scope(env, &scope);
1160 if (status != napi_ok) {
1161 return;
1162 }
1163 NG::AbilityContextInfo info;
1164 GetAbilityInfos(env, uiAbilityContext, info);
1165 for (auto listenerPair : abilityContextBeforePanStartListeners_) {
1166 auto ref = listenerPair.first;
1167 auto localInfo = beforePanStartInfos_[ref];
1168 if (info.IsEqual(localInfo)) {
1169 auto& holder = listenerPair.second;
1170 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1171 napi_close_handle_scope(env, scope);
1172 return;
1173 }
1174 holder.emplace_back(listener);
1175 napi_close_handle_scope(env, scope);
1176 return;
1177 }
1178 }
1179 napi_ref newRef = nullptr;
1180 napi_create_reference(env, uiAbilityContext, 1, &newRef);
1181 abilityContextBeforePanStartListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
1182 beforePanStartInfos_[newRef] = info;
1183 napi_close_handle_scope(env, scope);
1184 }
1185
RegisterBeforePanStartCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)1186 void UIObserver::RegisterBeforePanStartCallback(
1187 int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
1188 {
1189 if (uiContextInstanceId == 0) {
1190 uiContextInstanceId = Container::CurrentId();
1191 }
1192 auto iter = specifiedBeforePanStartListeners_.find(uiContextInstanceId);
1193 if (iter == specifiedBeforePanStartListeners_.end()) {
1194 specifiedBeforePanStartListeners_.emplace(
1195 uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
1196 return;
1197 }
1198 auto& holder = iter->second;
1199 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1200 return;
1201 }
1202 holder.emplace_back(listener);
1203 }
1204
UnRegisterBeforePanStartCallback(napi_env env,napi_value uiAbilityContext,napi_value callback)1205 void UIObserver::UnRegisterBeforePanStartCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
1206 {
1207 napi_handle_scope scope = nullptr;
1208 auto status = napi_open_handle_scope(env, &scope);
1209 if (status != napi_ok) {
1210 return;
1211 }
1212 NG::AbilityContextInfo info;
1213 GetAbilityInfos(env, uiAbilityContext, info);
1214 for (auto listenerPair : abilityContextBeforePanStartListeners_) {
1215 auto ref = listenerPair.first;
1216 auto localInfo = beforePanStartInfos_[ref];
1217 if (!info.IsEqual(localInfo)) {
1218 continue;
1219 }
1220 auto& holder = listenerPair.second;
1221 if (callback == nullptr) {
1222 holder.clear();
1223 } else {
1224 holder.erase(
1225 std::remove_if(
1226 holder.begin(),
1227 holder.end(),
1228 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1229 return registeredListener->NapiEqual(callback);
1230 }),
1231 holder.end());
1232 }
1233 if (holder.empty()) {
1234 beforePanStartInfos_.erase(ref);
1235 abilityContextBeforePanStartListeners_.erase(ref);
1236 napi_delete_reference(env, ref);
1237 }
1238 }
1239 napi_close_handle_scope(env, scope);
1240 }
1241
UnRegisterBeforePanStartCallback(int32_t uiContextInstanceId,napi_value callback)1242 void UIObserver::UnRegisterBeforePanStartCallback(int32_t uiContextInstanceId, napi_value callback)
1243 {
1244 if (uiContextInstanceId == 0) {
1245 uiContextInstanceId = Container::CurrentId();
1246 }
1247 auto iter = specifiedBeforePanStartListeners_.find(uiContextInstanceId);
1248 if (iter == specifiedBeforePanStartListeners_.end()) {
1249 return;
1250 }
1251 auto& holder = iter->second;
1252 if (callback == nullptr) {
1253 holder.clear();
1254 return;
1255 }
1256 holder.erase(
1257 std::remove_if(
1258 holder.begin(),
1259 holder.end(),
1260 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1261 return registeredListener->NapiEqual(callback);
1262 }),
1263 holder.end());
1264 }
1265
RegisterBeforePanEndCallback(napi_env env,napi_value uiAbilityContext,const std::shared_ptr<UIObserverListener> & listener)1266 void UIObserver::RegisterBeforePanEndCallback(
1267 napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
1268 {
1269 napi_handle_scope scope = nullptr;
1270 auto status = napi_open_handle_scope(env, &scope);
1271 if (status != napi_ok) {
1272 return;
1273 }
1274 NG::AbilityContextInfo info;
1275 GetAbilityInfos(env, uiAbilityContext, info);
1276 for (auto listenerPair : abilityContextBeforePanEndListeners_) {
1277 auto ref = listenerPair.first;
1278 auto localInfo = beforePanEndInfos_[ref];
1279 if (info.IsEqual(localInfo)) {
1280 auto& holder = listenerPair.second;
1281 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1282 napi_close_handle_scope(env, scope);
1283 return;
1284 }
1285 holder.emplace_back(listener);
1286 napi_close_handle_scope(env, scope);
1287 return;
1288 }
1289 }
1290 napi_ref newRef = nullptr;
1291 napi_create_reference(env, uiAbilityContext, 1, &newRef);
1292 abilityContextBeforePanEndListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
1293 beforePanEndInfos_[newRef] = info;
1294 napi_close_handle_scope(env, scope);
1295 }
1296
RegisterBeforePanEndCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)1297 void UIObserver::RegisterBeforePanEndCallback(
1298 int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
1299 {
1300 if (uiContextInstanceId == 0) {
1301 uiContextInstanceId = Container::CurrentId();
1302 }
1303 auto iter = specifiedBeforePanEndListeners_.find(uiContextInstanceId);
1304 if (iter == specifiedBeforePanEndListeners_.end()) {
1305 specifiedBeforePanEndListeners_.emplace(
1306 uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
1307 return;
1308 }
1309 auto& holder = iter->second;
1310 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1311 return;
1312 }
1313 holder.emplace_back(listener);
1314 }
1315
UnRegisterBeforePanEndCallback(napi_env env,napi_value uiAbilityContext,napi_value callback)1316 void UIObserver::UnRegisterBeforePanEndCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
1317 {
1318 napi_handle_scope scope = nullptr;
1319 auto status = napi_open_handle_scope(env, &scope);
1320 if (status != napi_ok) {
1321 return;
1322 }
1323 NG::AbilityContextInfo info;
1324 GetAbilityInfos(env, uiAbilityContext, info);
1325 for (auto listenerPair : abilityContextBeforePanEndListeners_) {
1326 auto ref = listenerPair.first;
1327 auto localInfo = beforePanEndInfos_[ref];
1328 if (!info.IsEqual(localInfo)) {
1329 continue;
1330 }
1331 auto& holder = listenerPair.second;
1332 if (callback == nullptr) {
1333 holder.clear();
1334 } else {
1335 holder.erase(
1336 std::remove_if(
1337 holder.begin(),
1338 holder.end(),
1339 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1340 return registeredListener->NapiEqual(callback);
1341 }),
1342 holder.end());
1343 }
1344 if (holder.empty()) {
1345 beforePanEndInfos_.erase(ref);
1346 abilityContextBeforePanEndListeners_.erase(ref);
1347 napi_delete_reference(env, ref);
1348 }
1349 }
1350 napi_close_handle_scope(env, scope);
1351 }
1352
UnRegisterBeforePanEndCallback(int32_t uiContextInstanceId,napi_value callback)1353 void UIObserver::UnRegisterBeforePanEndCallback(int32_t uiContextInstanceId, napi_value callback)
1354 {
1355 if (uiContextInstanceId == 0) {
1356 uiContextInstanceId = Container::CurrentId();
1357 }
1358 auto iter = specifiedBeforePanEndListeners_.find(uiContextInstanceId);
1359 if (iter == specifiedBeforePanEndListeners_.end()) {
1360 return;
1361 }
1362 auto& holder = iter->second;
1363 if (callback == nullptr) {
1364 holder.clear();
1365 return;
1366 }
1367 holder.erase(
1368 std::remove_if(
1369 holder.begin(),
1370 holder.end(),
1371 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1372 return registeredListener->NapiEqual(callback);
1373 }),
1374 holder.end());
1375 }
1376
RegisterAfterPanStartCallback(napi_env env,napi_value uiAbilityContext,const std::shared_ptr<UIObserverListener> & listener)1377 void UIObserver::RegisterAfterPanStartCallback(
1378 napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
1379 {
1380 napi_handle_scope scope = nullptr;
1381 auto status = napi_open_handle_scope(env, &scope);
1382 if (status != napi_ok) {
1383 return;
1384 }
1385 NG::AbilityContextInfo info;
1386 GetAbilityInfos(env, uiAbilityContext, info);
1387 for (auto listenerPair : abilityContextAfterPanStartListeners_) {
1388 auto ref = listenerPair.first;
1389 auto localInfo = afterPanStartInfos_[ref];
1390 if (info.IsEqual(localInfo)) {
1391 auto& holder = listenerPair.second;
1392 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1393 napi_close_handle_scope(env, scope);
1394 return;
1395 }
1396 holder.emplace_back(listener);
1397 napi_close_handle_scope(env, scope);
1398 return;
1399 }
1400 }
1401 napi_ref newRef = nullptr;
1402 napi_create_reference(env, uiAbilityContext, 1, &newRef);
1403 abilityContextAfterPanStartListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
1404 afterPanStartInfos_[newRef] = info;
1405 napi_close_handle_scope(env, scope);
1406 }
1407
RegisterAfterPanStartCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)1408 void UIObserver::RegisterAfterPanStartCallback(
1409 int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
1410 {
1411 if (uiContextInstanceId == 0) {
1412 uiContextInstanceId = Container::CurrentId();
1413 }
1414 auto iter = specifiedAfterPanStartListeners_.find(uiContextInstanceId);
1415 if (iter == specifiedAfterPanStartListeners_.end()) {
1416 specifiedAfterPanStartListeners_.emplace(
1417 uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
1418 return;
1419 }
1420 auto& holder = iter->second;
1421 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1422 return;
1423 }
1424 holder.emplace_back(listener);
1425 }
1426
UnRegisterAfterPanStartCallback(napi_env env,napi_value uiAbilityContext,napi_value callback)1427 void UIObserver::UnRegisterAfterPanStartCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
1428 {
1429 napi_handle_scope scope = nullptr;
1430 auto status = napi_open_handle_scope(env, &scope);
1431 if (status != napi_ok) {
1432 return;
1433 }
1434 NG::AbilityContextInfo info;
1435 GetAbilityInfos(env, uiAbilityContext, info);
1436 for (auto listenerPair : abilityContextAfterPanStartListeners_) {
1437 auto ref = listenerPair.first;
1438 auto localInfo = afterPanStartInfos_[ref];
1439 if (!info.IsEqual(localInfo)) {
1440 continue;
1441 }
1442 auto& holder = listenerPair.second;
1443 if (callback == nullptr) {
1444 holder.clear();
1445 } else {
1446 holder.erase(
1447 std::remove_if(
1448 holder.begin(),
1449 holder.end(),
1450 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1451 return registeredListener->NapiEqual(callback);
1452 }),
1453 holder.end());
1454 }
1455 if (holder.empty()) {
1456 afterPanStartInfos_.erase(ref);
1457 abilityContextAfterPanStartListeners_.erase(ref);
1458 napi_delete_reference(env, ref);
1459 }
1460 }
1461 napi_close_handle_scope(env, scope);
1462 }
1463
UnRegisterAfterPanStartCallback(int32_t uiContextInstanceId,napi_value callback)1464 void UIObserver::UnRegisterAfterPanStartCallback(int32_t uiContextInstanceId, napi_value callback)
1465 {
1466 if (uiContextInstanceId == 0) {
1467 uiContextInstanceId = Container::CurrentId();
1468 }
1469 auto iter = specifiedAfterPanStartListeners_.find(uiContextInstanceId);
1470 if (iter == specifiedAfterPanStartListeners_.end()) {
1471 return;
1472 }
1473 auto& holder = iter->second;
1474 if (callback == nullptr) {
1475 holder.clear();
1476 return;
1477 }
1478 holder.erase(
1479 std::remove_if(
1480 holder.begin(),
1481 holder.end(),
1482 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1483 return registeredListener->NapiEqual(callback);
1484 }),
1485 holder.end());
1486 }
1487
RegisterAfterPanEndCallback(napi_env env,napi_value uiAbilityContext,const std::shared_ptr<UIObserverListener> & listener)1488 void UIObserver::RegisterAfterPanEndCallback(
1489 napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
1490 {
1491 napi_handle_scope scope = nullptr;
1492 auto status = napi_open_handle_scope(env, &scope);
1493 if (status != napi_ok) {
1494 return;
1495 }
1496 NG::AbilityContextInfo info;
1497 GetAbilityInfos(env, uiAbilityContext, info);
1498 for (auto listenerPair : abilityContextAfterPanEndListeners_) {
1499 auto ref = listenerPair.first;
1500 auto localInfo = afterPanEndInfos_[ref];
1501 if (info.IsEqual(localInfo)) {
1502 auto& holder = listenerPair.second;
1503 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1504 napi_close_handle_scope(env, scope);
1505 return;
1506 }
1507 holder.emplace_back(listener);
1508 napi_close_handle_scope(env, scope);
1509 return;
1510 }
1511 }
1512 napi_ref newRef = nullptr;
1513 napi_create_reference(env, uiAbilityContext, 1, &newRef);
1514 abilityContextAfterPanEndListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
1515 afterPanEndInfos_[newRef] = info;
1516 napi_close_handle_scope(env, scope);
1517 }
1518
RegisterAfterPanEndCallback(int32_t uiContextInstanceId,const std::shared_ptr<UIObserverListener> & listener)1519 void UIObserver::RegisterAfterPanEndCallback(
1520 int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
1521 {
1522 if (uiContextInstanceId == 0) {
1523 uiContextInstanceId = Container::CurrentId();
1524 }
1525 auto iter = specifiedAfterPanEndListeners_.find(uiContextInstanceId);
1526 if (iter == specifiedAfterPanEndListeners_.end()) {
1527 specifiedAfterPanEndListeners_.emplace(
1528 uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
1529 return;
1530 }
1531 auto& holder = iter->second;
1532 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1533 return;
1534 }
1535 holder.emplace_back(listener);
1536 }
1537
UnRegisterAfterPanEndCallback(napi_env env,napi_value uiAbilityContext,napi_value callback)1538 void UIObserver::UnRegisterAfterPanEndCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
1539 {
1540 napi_handle_scope scope = nullptr;
1541 auto status = napi_open_handle_scope(env, &scope);
1542 if (status != napi_ok) {
1543 return;
1544 }
1545 NG::AbilityContextInfo info;
1546 GetAbilityInfos(env, uiAbilityContext, info);
1547 for (auto listenerPair : abilityContextAfterPanEndListeners_) {
1548 auto ref = listenerPair.first;
1549 auto localInfo = afterPanEndInfos_[ref];
1550 if (!info.IsEqual(localInfo)) {
1551 continue;
1552 }
1553 auto& holder = listenerPair.second;
1554 if (callback == nullptr) {
1555 holder.clear();
1556 } else {
1557 holder.erase(
1558 std::remove_if(
1559 holder.begin(),
1560 holder.end(),
1561 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1562 return registeredListener->NapiEqual(callback);
1563 }),
1564 holder.end());
1565 }
1566 if (holder.empty()) {
1567 afterPanEndInfos_.erase(ref);
1568 abilityContextAfterPanEndListeners_.erase(ref);
1569 napi_delete_reference(env, ref);
1570 }
1571 }
1572 napi_close_handle_scope(env, scope);
1573 }
1574
UnRegisterAfterPanEndCallback(int32_t uiContextInstanceId,napi_value callback)1575 void UIObserver::UnRegisterAfterPanEndCallback(int32_t uiContextInstanceId, napi_value callback)
1576 {
1577 if (uiContextInstanceId == 0) {
1578 uiContextInstanceId = Container::CurrentId();
1579 }
1580 auto iter = specifiedAfterPanEndListeners_.find(uiContextInstanceId);
1581 if (iter == specifiedAfterPanEndListeners_.end()) {
1582 return;
1583 }
1584 auto& holder = iter->second;
1585 if (callback == nullptr) {
1586 holder.clear();
1587 return;
1588 }
1589 holder.erase(
1590 std::remove_if(
1591 holder.begin(),
1592 holder.end(),
1593 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1594 return registeredListener->NapiEqual(callback);
1595 }),
1596 holder.end());
1597 }
1598
HandlePanGestureAccept(NG::AbilityContextInfo & info,const GestureEvent & gestureEventInfo,const RefPtr<NG::PanRecognizer> & current,const RefPtr<NG::FrameNode> & frameNode,const NG::PanGestureInfo & panGestureInfo)1599 void UIObserver::HandlePanGestureAccept(NG::AbilityContextInfo& info, const GestureEvent& gestureEventInfo,
1600 const RefPtr<NG::PanRecognizer>& current, const RefPtr<NG::FrameNode>& frameNode,
1601 const NG::PanGestureInfo& panGestureInfo)
1602 {
1603 auto env = GetCurrentNapiEnv();
1604 napi_handle_scope scope = nullptr;
1605 auto status = napi_open_handle_scope(env, &scope);
1606 if (status != napi_ok) {
1607 return;
1608 }
1609
1610 auto [listeners, specifiedListeners] = GetPanGestureListeners(panGestureInfo);
1611 if (listeners.empty() && specifiedListeners.empty()) {
1612 napi_close_handle_scope(env, scope);
1613 return;
1614 }
1615 for (auto& listenerPair : listeners) {
1616 auto ref = listenerPair.first;
1617 auto localInfo = PanGestureInfos_[ref];
1618 if (info.IsEqual(localInfo)) {
1619 napi_value abilityContext = nullptr;
1620 napi_get_reference_value(env, ref, &abilityContext);
1621
1622 auto& holder = listenerPair.second;
1623 for (const auto& listener : holder) {
1624 listener->OnPanGestureStateChange(gestureEventInfo, current, frameNode);
1625 }
1626 break;
1627 }
1628 }
1629
1630 auto currentId = Container::CurrentId();
1631 auto iter = specifiedListeners.find(currentId);
1632 if (iter == specifiedListeners.end()) {
1633 napi_close_handle_scope(env, scope);
1634 return;
1635 }
1636 auto& holder = iter->second;
1637 for (const auto& listener : holder) {
1638 listener->OnPanGestureStateChange(gestureEventInfo, current, frameNode);
1639 }
1640 napi_close_handle_scope(env, scope);
1641 }
1642
GetPanGestureListeners(const NG::PanGestureInfo & panGestureInfo)1643 UIObserver::PanGestureListenersPair UIObserver::GetPanGestureListeners(const NG::PanGestureInfo& panGestureInfo)
1644 {
1645 static std::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>> emptyListeners;
1646 static std::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>> emptySpecifiedListeners;
1647 if (panGestureInfo.callbackState == NG::CurrentCallbackState::START &&
1648 panGestureInfo.gestureState == NG::PanGestureState::BEFORE) {
1649 return { abilityContextBeforePanStartListeners_, specifiedBeforePanStartListeners_ };
1650 } else if (panGestureInfo.callbackState == NG::CurrentCallbackState::END &&
1651 panGestureInfo.gestureState == NG::PanGestureState::BEFORE) {
1652 return { abilityContextBeforePanEndListeners_, specifiedBeforePanEndListeners_ };
1653 } else if (panGestureInfo.callbackState == NG::CurrentCallbackState::START &&
1654 panGestureInfo.gestureState == NG::PanGestureState::AFTER) {
1655 return { abilityContextAfterPanStartListeners_, specifiedAfterPanStartListeners_ };
1656 } else if (panGestureInfo.callbackState == NG::CurrentCallbackState::END &&
1657 panGestureInfo.gestureState == NG::PanGestureState::AFTER) {
1658 return { abilityContextAfterPanEndListeners_, specifiedAfterPanEndListeners_ };
1659 } else {
1660 return { emptyListeners, emptySpecifiedListeners };
1661 }
1662 }
1663
RegisterNodeRenderStateChangeCallback(RefPtr<NG::FrameNode> frameNode,const std::shared_ptr<UIObserverListener> & listener,const RefPtr<NG::NodeRenderStatusMonitor> & monitor)1664 void UIObserver::RegisterNodeRenderStateChangeCallback(RefPtr<NG::FrameNode> frameNode,
1665 const std::shared_ptr<UIObserverListener>& listener, const RefPtr<NG::NodeRenderStatusMonitor>& monitor)
1666 {
1667 CHECK_NULL_VOID(frameNode);
1668 CHECK_NULL_VOID(monitor);
1669 auto frameNodePtr = AceType::RawPtr(frameNode);
1670
1671 auto iter = specifiedNodeRenderStateListeners_.find(frameNodePtr);
1672 if (iter == specifiedNodeRenderStateListeners_.end()) {
1673 auto nodeRenderStatusHandleFunc = [](NG::FrameNode* frameNode, NG::NodeRenderState state,
1674 NG::RenderMonitorReason reason) {
1675 CHECK_NULL_VOID(frameNode);
1676 auto iter = specifiedNodeRenderStateListeners_.find(frameNode);
1677 if (iter == specifiedNodeRenderStateListeners_.end()) {
1678 return;
1679 }
1680 CHECK_NULL_VOID(iter->second);
1681 for (const auto& listener : iter->second->listeners) {
1682 listener->OnNodeRenderStateChange(frameNode, state);
1683 }
1684 if (reason == NG::RenderMonitorReason::NODE_RELEASE) {
1685 specifiedNodeRenderStateListeners_.erase(frameNode);
1686 }
1687 };
1688 auto result = monitor->RegisterNodeRenderStatusListener(
1689 frameNodePtr, std::move(nodeRenderStatusHandleFunc), NG::MonitorSourceType::OBSERVER);
1690 if (result.id != NG::MONITOR_INVALID_ID) {
1691 specifiedNodeRenderStateListeners_.emplace(
1692 frameNodePtr, std::make_shared<NodeRenderListener>(
1693 result.id, std::list<std::shared_ptr<UIObserverListener>>({ listener })));
1694 }
1695 listener->OnNodeRenderStateChange(frameNodePtr, result.state);
1696 return;
1697 }
1698 CHECK_NULL_VOID(iter->second);
1699 auto& holder = iter->second->listeners;
1700 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1701 return;
1702 }
1703 holder.emplace_back(listener);
1704 listener->OnNodeRenderStateChange(frameNodePtr, monitor->GetNodeCurrentRenderState(frameNodePtr));
1705 }
1706
UnRegisterNodeRenderStateChangeCallback(RefPtr<NG::FrameNode> frameNode,napi_value callback,const RefPtr<NG::NodeRenderStatusMonitor> & monitor)1707 void UIObserver::UnRegisterNodeRenderStateChangeCallback(
1708 RefPtr<NG::FrameNode> frameNode, napi_value callback, const RefPtr<NG::NodeRenderStatusMonitor>& monitor)
1709 {
1710 CHECK_NULL_VOID(frameNode);
1711 CHECK_NULL_VOID(monitor);
1712 auto frameNodePtr = AceType::RawPtr(frameNode);
1713 auto iter = specifiedNodeRenderStateListeners_.find(frameNodePtr);
1714 if (iter == specifiedNodeRenderStateListeners_.end()) {
1715 return;
1716 }
1717 CHECK_NULL_VOID(iter->second);
1718 auto& holder = iter->second->listeners;
1719 if (callback == nullptr) {
1720 holder.clear();
1721 specifiedNodeRenderStateListeners_.erase(AceType::RawPtr(frameNode));
1722 monitor->UnRegisterNodeRenderStatusListener(frameNodePtr, iter->second->id);
1723 return;
1724 }
1725 holder.erase(
1726 std::remove_if(
1727 holder.begin(),
1728 holder.end(),
1729 [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
1730 return registeredListener->NapiEqual(callback);
1731 }),
1732 holder.end());
1733 if (holder.empty()) {
1734 specifiedNodeRenderStateListeners_.erase(AceType::RawPtr(frameNode));
1735 monitor->UnRegisterNodeRenderStatusListener(frameNodePtr, iter->second->id);
1736 }
1737 }
1738
1739 // UIObserver.on(type: "tabContentState", callback)
1740 // register a global listener without options
RegisterTabContentStateCallback(const std::shared_ptr<UIObserverListener> & listener)1741 void UIObserver::RegisterTabContentStateCallback(const std::shared_ptr<UIObserverListener>& listener)
1742 {
1743 if (std::find(tabContentStateListeners_.begin(), tabContentStateListeners_.end(), listener) !=
1744 tabContentStateListeners_.end()) {
1745 return;
1746 }
1747 tabContentStateListeners_.emplace_back(listener);
1748 }
1749
1750 // UIObserver.on(type: "tabContentState", options, callback)
1751 // register a listener on a specified tabContentState
RegisterTabContentStateCallback(const std::string & id,const std::shared_ptr<UIObserverListener> & listener)1752 void UIObserver::RegisterTabContentStateCallback(
1753 const std::string& id, const std::shared_ptr<UIObserverListener>& listener)
1754 {
1755 auto iter = specifiedTabContentStateListeners_.find(id);
1756 if (iter == specifiedTabContentStateListeners_.end()) {
1757 specifiedTabContentStateListeners_.emplace(id, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
1758 return;
1759 }
1760 auto& holder = iter->second;
1761 if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
1762 return;
1763 }
1764 holder.emplace_back(listener);
1765 }
1766
1767 // UIObserver.off(type: "tabContentState", callback)
UnRegisterTabContentStateCallback(napi_value cb)1768 void UIObserver::UnRegisterTabContentStateCallback(napi_value cb)
1769 {
1770 if (cb == nullptr) {
1771 tabContentStateListeners_.clear();
1772 return;
1773 }
1774
1775 tabContentStateListeners_.erase(
1776 std::remove_if(
1777 tabContentStateListeners_.begin(),
1778 tabContentStateListeners_.end(),
1779 [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
1780 return registeredListener->NapiEqual(cb);
1781 }),
1782 tabContentStateListeners_.end()
1783 );
1784 }
1785
1786 // UIObserver.off(type: "tabContentState", options, callback)
UnRegisterTabContentStateCallback(const std::string & id,napi_value cb)1787 void UIObserver::UnRegisterTabContentStateCallback(const std::string& id, napi_value cb)
1788 {
1789 auto iter = specifiedTabContentStateListeners_.find(id);
1790 if (iter == specifiedTabContentStateListeners_.end()) {
1791 return;
1792 }
1793 auto& holder = iter->second;
1794 if (cb == nullptr) {
1795 holder.clear();
1796 return;
1797 }
1798 holder.erase(
1799 std::remove_if(
1800 holder.begin(),
1801 holder.end(),
1802 [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
1803 return registeredListener->NapiEqual(cb);
1804 }),
1805 holder.end()
1806 );
1807 }
1808
HandleTabContentStateChange(const NG::TabContentInfo & tabContentInfo)1809 void UIObserver::HandleTabContentStateChange(const NG::TabContentInfo& tabContentInfo)
1810 {
1811 for (const auto& listener : tabContentStateListeners_) {
1812 listener->OnTabContentStateChange(tabContentInfo);
1813 }
1814
1815 auto iter = specifiedTabContentStateListeners_.find(tabContentInfo.id);
1816 if (iter == specifiedTabContentStateListeners_.end()) {
1817 return;
1818 }
1819
1820 auto& holder = iter->second;
1821
1822 for (const auto& listener : holder) {
1823 listener->OnTabContentStateChange(tabContentInfo);
1824 }
1825 }
1826
GetAbilityInfos(napi_env env,napi_value abilityContext,NG::AbilityContextInfo & info)1827 void UIObserver::GetAbilityInfos(napi_env env, napi_value abilityContext, NG::AbilityContextInfo& info)
1828 {
1829 if (!env || !abilityContext) {
1830 return;
1831 }
1832 napi_value napiInfo = nullptr;
1833 napi_get_named_property(env, abilityContext, "abilityInfo", &napiInfo);
1834 CHECK_NULL_VOID(napiInfo);
1835 napi_value name = nullptr;
1836 napi_get_named_property(env, napiInfo, "name", &name);
1837 ParseStringFromNapi(env, name, info.name);
1838 napi_get_named_property(env, napiInfo, "bundleName", &name);
1839 ParseStringFromNapi(env, name, info.bundleName);
1840 napi_get_named_property(env, napiInfo, "moduleName", &name);
1841 ParseStringFromNapi(env, name, info.moduleName);
1842 }
1843
ParseStringFromNapi(napi_env env,napi_value val,std::string & str)1844 bool UIObserver::ParseStringFromNapi(napi_env env, napi_value val, std::string& str)
1845 {
1846 if (!val || !MatchValueType(env, val, napi_string)) {
1847 return false;
1848 }
1849 size_t len = 0;
1850 napi_get_value_string_utf8(env, val, nullptr, 0, &len);
1851 std::unique_ptr<char[]> result = std::make_unique<char[]>(len + 1);
1852 napi_get_value_string_utf8(env, val, result.get(), len + 1, &len);
1853 str = result.get();
1854 return true;
1855 }
1856
MatchValueType(napi_env env,napi_value value,napi_valuetype targetType)1857 bool UIObserver::MatchValueType(napi_env env, napi_value value, napi_valuetype targetType)
1858 {
1859 napi_valuetype valueType = napi_undefined;
1860 napi_typeof(env, value, &valueType);
1861 return valueType == targetType;
1862 }
1863
GetCurrentNapiEnv()1864 napi_env UIObserver::GetCurrentNapiEnv()
1865 {
1866 auto engine = EngineHelper::GetCurrentEngine();
1867 CHECK_NULL_RETURN(engine, nullptr);
1868 NativeEngine* nativeEngine = engine->GetNativeEngine();
1869 CHECK_NULL_RETURN(nativeEngine, nullptr);
1870 return reinterpret_cast<napi_env>(nativeEngine);
1871 }
1872 } // namespace OHOS::Ace::Napi
1873