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