123b3eb3cSopenharmony_ci/*
223b3eb3cSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
323b3eb3cSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
423b3eb3cSopenharmony_ci * you may not use this file except in compliance with the License.
523b3eb3cSopenharmony_ci * You may obtain a copy of the License at
623b3eb3cSopenharmony_ci *
723b3eb3cSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
823b3eb3cSopenharmony_ci *
923b3eb3cSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1023b3eb3cSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1123b3eb3cSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1223b3eb3cSopenharmony_ci * See the License for the specific language governing permissions and
1323b3eb3cSopenharmony_ci * limitations under the License.
1423b3eb3cSopenharmony_ci */
1523b3eb3cSopenharmony_ci
1623b3eb3cSopenharmony_ci#include "ui_observer.h"
1723b3eb3cSopenharmony_ci
1823b3eb3cSopenharmony_ci#include "bridge/common/utils/engine_helper.h"
1923b3eb3cSopenharmony_ci
2023b3eb3cSopenharmony_ci
2123b3eb3cSopenharmony_cinamespace OHOS::Ace::Napi {
2223b3eb3cSopenharmony_cistd::list<std::shared_ptr<UIObserverListener>> UIObserver::unspecifiedNavigationListeners_;
2323b3eb3cSopenharmony_cistd::unordered_map<std::string, std::list<std::shared_ptr<UIObserverListener>>>
2423b3eb3cSopenharmony_ci    UIObserver::specifiedCNavigationListeners_;
2523b3eb3cSopenharmony_ci
2623b3eb3cSopenharmony_cistd::list<std::shared_ptr<UIObserverListener>> UIObserver::scrollEventListeners_;
2723b3eb3cSopenharmony_cistd::unordered_map<std::string, std::list<std::shared_ptr<UIObserverListener>>>
2823b3eb3cSopenharmony_ci    UIObserver::specifiedScrollEventListeners_;
2923b3eb3cSopenharmony_ci
3023b3eb3cSopenharmony_cistd::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
3123b3eb3cSopenharmony_ci    UIObserver::abilityContextRouterPageListeners_;
3223b3eb3cSopenharmony_cistd::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
3323b3eb3cSopenharmony_ci    UIObserver::specifiedRouterPageListeners_;
3423b3eb3cSopenharmony_cistd::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::infosForRouterPage_;
3523b3eb3cSopenharmony_ci
3623b3eb3cSopenharmony_cistd::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
3723b3eb3cSopenharmony_ci    UIObserver::specifiedDensityListeners_;
3823b3eb3cSopenharmony_cistd::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>> UIObserver::specifiedDrawListeners_;
3923b3eb3cSopenharmony_cistd::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>> UIObserver::specifiedLayoutListeners_;
4023b3eb3cSopenharmony_ci
4123b3eb3cSopenharmony_cistd::unordered_map<napi_ref, UIObserver::NavIdAndListenersMap> UIObserver::abilityUIContextNavDesSwitchListeners_;
4223b3eb3cSopenharmony_cistd::unordered_map<int32_t, UIObserver::NavIdAndListenersMap> UIObserver::uiContextNavDesSwitchListeners_;
4323b3eb3cSopenharmony_cistd::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::infosForNavDesSwitch_;
4423b3eb3cSopenharmony_ci
4523b3eb3cSopenharmony_cistd::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
4623b3eb3cSopenharmony_ci    UIObserver::abilityContextWillClickListeners_;
4723b3eb3cSopenharmony_cistd::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
4823b3eb3cSopenharmony_ci    UIObserver::specifiedWillClickListeners_;
4923b3eb3cSopenharmony_cistd::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::willClickInfos_;
5023b3eb3cSopenharmony_ci
5123b3eb3cSopenharmony_cistd::unordered_map<napi_ref, std::list<std::shared_ptr<UIObserverListener>>>
5223b3eb3cSopenharmony_ci    UIObserver::abilityContextDidClickListeners_;
5323b3eb3cSopenharmony_cistd::unordered_map<int32_t, std::list<std::shared_ptr<UIObserverListener>>>
5423b3eb3cSopenharmony_ci    UIObserver::specifiedDidClickListeners_;
5523b3eb3cSopenharmony_cistd::unordered_map<napi_ref, NG::AbilityContextInfo> UIObserver::didClickInfos_;
5623b3eb3cSopenharmony_ci
5723b3eb3cSopenharmony_cistd::list<std::shared_ptr<UIObserverListener>> UIObserver::tabContentStateListeners_;
5823b3eb3cSopenharmony_cistd::unordered_map<std::string, std::list<std::shared_ptr<UIObserverListener>>>
5923b3eb3cSopenharmony_ci    UIObserver::specifiedTabContentStateListeners_;
6023b3eb3cSopenharmony_ci
6123b3eb3cSopenharmony_ci// UIObserver.on(type: "navDestinationUpdate", callback)
6223b3eb3cSopenharmony_ci// register a global listener without options
6323b3eb3cSopenharmony_civoid UIObserver::RegisterNavigationCallback(const std::shared_ptr<UIObserverListener>& listener)
6423b3eb3cSopenharmony_ci{
6523b3eb3cSopenharmony_ci    if (std::find(unspecifiedNavigationListeners_.begin(), unspecifiedNavigationListeners_.end(), listener) !=
6623b3eb3cSopenharmony_ci        unspecifiedNavigationListeners_.end()) {
6723b3eb3cSopenharmony_ci        return;
6823b3eb3cSopenharmony_ci    }
6923b3eb3cSopenharmony_ci    unspecifiedNavigationListeners_.emplace_back(listener);
7023b3eb3cSopenharmony_ci}
7123b3eb3cSopenharmony_ci
7223b3eb3cSopenharmony_ci// UIObserver.on(type: "navDestinationUpdate", options, callback)
7323b3eb3cSopenharmony_ci// register a listener on a specified Navigation
7423b3eb3cSopenharmony_civoid UIObserver::RegisterNavigationCallback(
7523b3eb3cSopenharmony_ci    std::string navigationId, const std::shared_ptr<UIObserverListener>& listener)
7623b3eb3cSopenharmony_ci{
7723b3eb3cSopenharmony_ci    auto iter = specifiedCNavigationListeners_.find(navigationId);
7823b3eb3cSopenharmony_ci    if (iter == specifiedCNavigationListeners_.end()) {
7923b3eb3cSopenharmony_ci        specifiedCNavigationListeners_.emplace(
8023b3eb3cSopenharmony_ci            navigationId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
8123b3eb3cSopenharmony_ci        return;
8223b3eb3cSopenharmony_ci    }
8323b3eb3cSopenharmony_ci    auto& holder = iter->second;
8423b3eb3cSopenharmony_ci    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
8523b3eb3cSopenharmony_ci        return;
8623b3eb3cSopenharmony_ci    }
8723b3eb3cSopenharmony_ci    holder.emplace_back(listener);
8823b3eb3cSopenharmony_ci}
8923b3eb3cSopenharmony_ci
9023b3eb3cSopenharmony_ci// UIObserver.off(type: "navDestinationUpdate", callback)
9123b3eb3cSopenharmony_civoid UIObserver::UnRegisterNavigationCallback(napi_value cb)
9223b3eb3cSopenharmony_ci{
9323b3eb3cSopenharmony_ci    if (cb == nullptr) {
9423b3eb3cSopenharmony_ci        unspecifiedNavigationListeners_.clear();
9523b3eb3cSopenharmony_ci        return;
9623b3eb3cSopenharmony_ci    }
9723b3eb3cSopenharmony_ci
9823b3eb3cSopenharmony_ci    unspecifiedNavigationListeners_.erase(
9923b3eb3cSopenharmony_ci        std::remove_if(
10023b3eb3cSopenharmony_ci            unspecifiedNavigationListeners_.begin(),
10123b3eb3cSopenharmony_ci            unspecifiedNavigationListeners_.end(),
10223b3eb3cSopenharmony_ci            [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
10323b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(cb);
10423b3eb3cSopenharmony_ci            }
10523b3eb3cSopenharmony_ci        ),
10623b3eb3cSopenharmony_ci        unspecifiedNavigationListeners_.end()
10723b3eb3cSopenharmony_ci    );
10823b3eb3cSopenharmony_ci}
10923b3eb3cSopenharmony_ci
11023b3eb3cSopenharmony_ci// UIObserver.off(type: "navDestinationUpdate", options, callback)
11123b3eb3cSopenharmony_civoid UIObserver::UnRegisterNavigationCallback(std::string navigationId, napi_value cb)
11223b3eb3cSopenharmony_ci{
11323b3eb3cSopenharmony_ci    auto iter = specifiedCNavigationListeners_.find(navigationId);
11423b3eb3cSopenharmony_ci    if (iter == specifiedCNavigationListeners_.end()) {
11523b3eb3cSopenharmony_ci        return;
11623b3eb3cSopenharmony_ci    }
11723b3eb3cSopenharmony_ci    auto& holder = iter->second;
11823b3eb3cSopenharmony_ci    if (cb == nullptr) {
11923b3eb3cSopenharmony_ci        holder.clear();
12023b3eb3cSopenharmony_ci        return;
12123b3eb3cSopenharmony_ci    }
12223b3eb3cSopenharmony_ci    holder.erase(
12323b3eb3cSopenharmony_ci        std::remove_if(
12423b3eb3cSopenharmony_ci            holder.begin(),
12523b3eb3cSopenharmony_ci            holder.end(),
12623b3eb3cSopenharmony_ci            [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
12723b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(cb);
12823b3eb3cSopenharmony_ci            }
12923b3eb3cSopenharmony_ci        ),
13023b3eb3cSopenharmony_ci        holder.end()
13123b3eb3cSopenharmony_ci    );
13223b3eb3cSopenharmony_ci}
13323b3eb3cSopenharmony_ci
13423b3eb3cSopenharmony_civoid UIObserver::HandleNavigationStateChange(const NG::NavDestinationInfo& info)
13523b3eb3cSopenharmony_ci{
13623b3eb3cSopenharmony_ci    auto unspecifiedHolder = unspecifiedNavigationListeners_;
13723b3eb3cSopenharmony_ci    for (const auto& listener : unspecifiedHolder) {
13823b3eb3cSopenharmony_ci        listener->OnNavigationStateChange(info);
13923b3eb3cSopenharmony_ci    }
14023b3eb3cSopenharmony_ci    auto iter = specifiedCNavigationListeners_.find(info.navigationId);
14123b3eb3cSopenharmony_ci    if (iter == specifiedCNavigationListeners_.end()) {
14223b3eb3cSopenharmony_ci        return;
14323b3eb3cSopenharmony_ci    }
14423b3eb3cSopenharmony_ci
14523b3eb3cSopenharmony_ci    auto holder = iter->second;
14623b3eb3cSopenharmony_ci
14723b3eb3cSopenharmony_ci    for (const auto& listener : holder) {
14823b3eb3cSopenharmony_ci        listener->OnNavigationStateChange(info);
14923b3eb3cSopenharmony_ci    }
15023b3eb3cSopenharmony_ci}
15123b3eb3cSopenharmony_ci
15223b3eb3cSopenharmony_ci// UIObserver.on(type: "scrollEvent", callback)
15323b3eb3cSopenharmony_ci// register a global listener without options
15423b3eb3cSopenharmony_civoid UIObserver::RegisterScrollEventCallback(const std::shared_ptr<UIObserverListener>& listener)
15523b3eb3cSopenharmony_ci{
15623b3eb3cSopenharmony_ci    if (std::find(scrollEventListeners_.begin(), scrollEventListeners_.end(), listener) !=
15723b3eb3cSopenharmony_ci        scrollEventListeners_.end()) {
15823b3eb3cSopenharmony_ci        return;
15923b3eb3cSopenharmony_ci    }
16023b3eb3cSopenharmony_ci    scrollEventListeners_.emplace_back(listener);
16123b3eb3cSopenharmony_ci}
16223b3eb3cSopenharmony_ci
16323b3eb3cSopenharmony_ci// UIObserver.on(type: "scrollEvent", options, callback)
16423b3eb3cSopenharmony_ci// register a listener on a specified scrollEvent
16523b3eb3cSopenharmony_civoid UIObserver::RegisterScrollEventCallback(
16623b3eb3cSopenharmony_ci    const std::string& id, const std::shared_ptr<UIObserverListener>& listener)
16723b3eb3cSopenharmony_ci{
16823b3eb3cSopenharmony_ci    auto iter = specifiedScrollEventListeners_.find(id);
16923b3eb3cSopenharmony_ci    if (iter == specifiedScrollEventListeners_.end()) {
17023b3eb3cSopenharmony_ci        specifiedScrollEventListeners_.emplace(id, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
17123b3eb3cSopenharmony_ci        return;
17223b3eb3cSopenharmony_ci    }
17323b3eb3cSopenharmony_ci    auto& holder = iter->second;
17423b3eb3cSopenharmony_ci    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
17523b3eb3cSopenharmony_ci        return;
17623b3eb3cSopenharmony_ci    }
17723b3eb3cSopenharmony_ci    holder.emplace_back(listener);
17823b3eb3cSopenharmony_ci}
17923b3eb3cSopenharmony_ci
18023b3eb3cSopenharmony_ci// UIObserver.off(type: "scrollEvent", callback)
18123b3eb3cSopenharmony_civoid UIObserver::UnRegisterScrollEventCallback(napi_value cb)
18223b3eb3cSopenharmony_ci{
18323b3eb3cSopenharmony_ci    if (cb == nullptr) {
18423b3eb3cSopenharmony_ci        scrollEventListeners_.clear();
18523b3eb3cSopenharmony_ci        return;
18623b3eb3cSopenharmony_ci    }
18723b3eb3cSopenharmony_ci
18823b3eb3cSopenharmony_ci    scrollEventListeners_.erase(
18923b3eb3cSopenharmony_ci        std::remove_if(
19023b3eb3cSopenharmony_ci            scrollEventListeners_.begin(),
19123b3eb3cSopenharmony_ci            scrollEventListeners_.end(),
19223b3eb3cSopenharmony_ci            [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
19323b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(cb);
19423b3eb3cSopenharmony_ci            }),
19523b3eb3cSopenharmony_ci        scrollEventListeners_.end()
19623b3eb3cSopenharmony_ci    );
19723b3eb3cSopenharmony_ci}
19823b3eb3cSopenharmony_ci
19923b3eb3cSopenharmony_ci// UIObserver.off(type: "scrollEvent", options, callback)
20023b3eb3cSopenharmony_civoid UIObserver::UnRegisterScrollEventCallback(const std::string& id, napi_value cb)
20123b3eb3cSopenharmony_ci{
20223b3eb3cSopenharmony_ci    auto iter = specifiedScrollEventListeners_.find(id);
20323b3eb3cSopenharmony_ci    if (iter == specifiedScrollEventListeners_.end()) {
20423b3eb3cSopenharmony_ci        return;
20523b3eb3cSopenharmony_ci    }
20623b3eb3cSopenharmony_ci    auto& holder = iter->second;
20723b3eb3cSopenharmony_ci    if (cb == nullptr) {
20823b3eb3cSopenharmony_ci        holder.clear();
20923b3eb3cSopenharmony_ci        return;
21023b3eb3cSopenharmony_ci    }
21123b3eb3cSopenharmony_ci    holder.erase(
21223b3eb3cSopenharmony_ci        std::remove_if(
21323b3eb3cSopenharmony_ci            holder.begin(),
21423b3eb3cSopenharmony_ci            holder.end(),
21523b3eb3cSopenharmony_ci            [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
21623b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(cb);
21723b3eb3cSopenharmony_ci            }),
21823b3eb3cSopenharmony_ci        holder.end()
21923b3eb3cSopenharmony_ci    );
22023b3eb3cSopenharmony_ci}
22123b3eb3cSopenharmony_ci
22223b3eb3cSopenharmony_civoid UIObserver::HandleScrollEventStateChange(const std::string& id, int32_t uniqueId,
22323b3eb3cSopenharmony_ci    NG::ScrollEventType eventType, float offset)
22423b3eb3cSopenharmony_ci{
22523b3eb3cSopenharmony_ci    for (const auto& listener : scrollEventListeners_) {
22623b3eb3cSopenharmony_ci        listener->OnScrollEventStateChange(id, uniqueId, eventType, offset);
22723b3eb3cSopenharmony_ci    }
22823b3eb3cSopenharmony_ci
22923b3eb3cSopenharmony_ci    auto iter = specifiedScrollEventListeners_.find(id);
23023b3eb3cSopenharmony_ci    if (iter == specifiedScrollEventListeners_.end()) {
23123b3eb3cSopenharmony_ci        return;
23223b3eb3cSopenharmony_ci    }
23323b3eb3cSopenharmony_ci
23423b3eb3cSopenharmony_ci    auto& holder = iter->second;
23523b3eb3cSopenharmony_ci
23623b3eb3cSopenharmony_ci    for (const auto& listener : holder) {
23723b3eb3cSopenharmony_ci        listener->OnScrollEventStateChange(id, uniqueId, eventType, offset);
23823b3eb3cSopenharmony_ci    }
23923b3eb3cSopenharmony_ci}
24023b3eb3cSopenharmony_ci
24123b3eb3cSopenharmony_ci// UIObserver.on(type: "routerPageUpdate", UIAbilityContext, callback)
24223b3eb3cSopenharmony_ci// register a listener on current page
24323b3eb3cSopenharmony_civoid UIObserver::RegisterRouterPageCallback(
24423b3eb3cSopenharmony_ci    napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
24523b3eb3cSopenharmony_ci{
24623b3eb3cSopenharmony_ci    NG::AbilityContextInfo info;
24723b3eb3cSopenharmony_ci    GetAbilityInfos(env, uiAbilityContext, info);
24823b3eb3cSopenharmony_ci    for (auto listenerPair : abilityContextRouterPageListeners_) {
24923b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
25023b3eb3cSopenharmony_ci        auto localInfo = infosForRouterPage_[ref];
25123b3eb3cSopenharmony_ci        if (info.IsEqual(localInfo)) {
25223b3eb3cSopenharmony_ci            auto& holder = abilityContextRouterPageListeners_[ref];
25323b3eb3cSopenharmony_ci            if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
25423b3eb3cSopenharmony_ci                return;
25523b3eb3cSopenharmony_ci            }
25623b3eb3cSopenharmony_ci            holder.emplace_back(listener);
25723b3eb3cSopenharmony_ci            return;
25823b3eb3cSopenharmony_ci        }
25923b3eb3cSopenharmony_ci    }
26023b3eb3cSopenharmony_ci    napi_ref newRef = nullptr;
26123b3eb3cSopenharmony_ci    napi_create_reference(env, uiAbilityContext, 1, &newRef);
26223b3eb3cSopenharmony_ci    abilityContextRouterPageListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
26323b3eb3cSopenharmony_ci    infosForRouterPage_[newRef] = info;
26423b3eb3cSopenharmony_ci}
26523b3eb3cSopenharmony_ci
26623b3eb3cSopenharmony_ci// UIObserver.on(type: "routerPageUpdate", uiContext | null, callback)
26723b3eb3cSopenharmony_ci// register a listener on current page
26823b3eb3cSopenharmony_civoid UIObserver::RegisterRouterPageCallback(
26923b3eb3cSopenharmony_ci    int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
27023b3eb3cSopenharmony_ci{
27123b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
27223b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
27323b3eb3cSopenharmony_ci    }
27423b3eb3cSopenharmony_ci    auto iter = specifiedRouterPageListeners_.find(uiContextInstanceId);
27523b3eb3cSopenharmony_ci    if (iter == specifiedRouterPageListeners_.end()) {
27623b3eb3cSopenharmony_ci        specifiedRouterPageListeners_.emplace(
27723b3eb3cSopenharmony_ci            uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
27823b3eb3cSopenharmony_ci        return;
27923b3eb3cSopenharmony_ci    }
28023b3eb3cSopenharmony_ci    auto& holder = iter->second;
28123b3eb3cSopenharmony_ci    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
28223b3eb3cSopenharmony_ci        return;
28323b3eb3cSopenharmony_ci    }
28423b3eb3cSopenharmony_ci    holder.emplace_back(listener);
28523b3eb3cSopenharmony_ci}
28623b3eb3cSopenharmony_ci
28723b3eb3cSopenharmony_ci// UIObserver.off(type: "routerPageUpdate", uiAbilityContext, callback)
28823b3eb3cSopenharmony_civoid UIObserver::UnRegisterRouterPageCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
28923b3eb3cSopenharmony_ci{
29023b3eb3cSopenharmony_ci    NG::AbilityContextInfo info;
29123b3eb3cSopenharmony_ci    GetAbilityInfos(env, uiAbilityContext, info);
29223b3eb3cSopenharmony_ci    for (auto listenerPair : abilityContextRouterPageListeners_) {
29323b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
29423b3eb3cSopenharmony_ci        auto localInfo = infosForRouterPage_[ref];
29523b3eb3cSopenharmony_ci        if (info.IsEqual(localInfo)) {
29623b3eb3cSopenharmony_ci            auto& holder = abilityContextRouterPageListeners_[listenerPair.first];
29723b3eb3cSopenharmony_ci            if (callback == nullptr) {
29823b3eb3cSopenharmony_ci                holder.clear();
29923b3eb3cSopenharmony_ci            } else {
30023b3eb3cSopenharmony_ci                holder.erase(
30123b3eb3cSopenharmony_ci                    std::remove_if(
30223b3eb3cSopenharmony_ci                        holder.begin(),
30323b3eb3cSopenharmony_ci                        holder.end(),
30423b3eb3cSopenharmony_ci                        [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
30523b3eb3cSopenharmony_ci                            return registeredListener->NapiEqual(callback);
30623b3eb3cSopenharmony_ci                        }),
30723b3eb3cSopenharmony_ci                    holder.end());
30823b3eb3cSopenharmony_ci            }
30923b3eb3cSopenharmony_ci            if (holder.empty()) {
31023b3eb3cSopenharmony_ci                infosForRouterPage_.erase(ref);
31123b3eb3cSopenharmony_ci                abilityContextRouterPageListeners_.erase(ref);
31223b3eb3cSopenharmony_ci                napi_delete_reference(env, ref);
31323b3eb3cSopenharmony_ci            }
31423b3eb3cSopenharmony_ci            return;
31523b3eb3cSopenharmony_ci        }
31623b3eb3cSopenharmony_ci    }
31723b3eb3cSopenharmony_ci}
31823b3eb3cSopenharmony_ci
31923b3eb3cSopenharmony_ci// UIObserver.off(type: "routerPageUpdate", uiContext | null, callback)
32023b3eb3cSopenharmony_civoid UIObserver::UnRegisterRouterPageCallback(int32_t uiContextInstanceId, napi_value callback)
32123b3eb3cSopenharmony_ci{
32223b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
32323b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
32423b3eb3cSopenharmony_ci    }
32523b3eb3cSopenharmony_ci    auto iter = specifiedRouterPageListeners_.find(uiContextInstanceId);
32623b3eb3cSopenharmony_ci    if (iter == specifiedRouterPageListeners_.end()) {
32723b3eb3cSopenharmony_ci        return;
32823b3eb3cSopenharmony_ci    }
32923b3eb3cSopenharmony_ci    auto& holder = iter->second;
33023b3eb3cSopenharmony_ci    if (callback == nullptr) {
33123b3eb3cSopenharmony_ci        holder.clear();
33223b3eb3cSopenharmony_ci        return;
33323b3eb3cSopenharmony_ci    }
33423b3eb3cSopenharmony_ci    holder.erase(
33523b3eb3cSopenharmony_ci        std::remove_if(
33623b3eb3cSopenharmony_ci            holder.begin(),
33723b3eb3cSopenharmony_ci            holder.end(),
33823b3eb3cSopenharmony_ci            [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
33923b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(callback);
34023b3eb3cSopenharmony_ci            }),
34123b3eb3cSopenharmony_ci        holder.end());
34223b3eb3cSopenharmony_ci}
34323b3eb3cSopenharmony_ci
34423b3eb3cSopenharmony_ci// UIObserver.on(type: "willDraw", uiContext | null, callback)
34523b3eb3cSopenharmony_ci// register a listener on current page
34623b3eb3cSopenharmony_civoid UIObserver::RegisterDrawCallback(int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
34723b3eb3cSopenharmony_ci{
34823b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
34923b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
35023b3eb3cSopenharmony_ci    }
35123b3eb3cSopenharmony_ci    if (specifiedDrawListeners_.find(uiContextInstanceId) == specifiedDrawListeners_.end()) {
35223b3eb3cSopenharmony_ci        specifiedDrawListeners_[uiContextInstanceId] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
35323b3eb3cSopenharmony_ci        return;
35423b3eb3cSopenharmony_ci    }
35523b3eb3cSopenharmony_ci    auto& holder = specifiedDrawListeners_[uiContextInstanceId];
35623b3eb3cSopenharmony_ci    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
35723b3eb3cSopenharmony_ci        return;
35823b3eb3cSopenharmony_ci    }
35923b3eb3cSopenharmony_ci    holder.emplace_back(listener);
36023b3eb3cSopenharmony_ci}
36123b3eb3cSopenharmony_ci
36223b3eb3cSopenharmony_ci// UIObserver.off(type: "willDraw", uiContext | null, callback)
36323b3eb3cSopenharmony_civoid UIObserver::UnRegisterDrawCallback(int32_t uiContextInstanceId, napi_value callback)
36423b3eb3cSopenharmony_ci{
36523b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
36623b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
36723b3eb3cSopenharmony_ci    }
36823b3eb3cSopenharmony_ci    if (specifiedDrawListeners_.find(uiContextInstanceId) == specifiedDrawListeners_.end()) {
36923b3eb3cSopenharmony_ci        return;
37023b3eb3cSopenharmony_ci    }
37123b3eb3cSopenharmony_ci    auto& holder = specifiedDrawListeners_[uiContextInstanceId];
37223b3eb3cSopenharmony_ci    if (callback == nullptr) {
37323b3eb3cSopenharmony_ci        holder.clear();
37423b3eb3cSopenharmony_ci        return;
37523b3eb3cSopenharmony_ci    }
37623b3eb3cSopenharmony_ci    holder.erase(
37723b3eb3cSopenharmony_ci        std::remove_if(
37823b3eb3cSopenharmony_ci            holder.begin(),
37923b3eb3cSopenharmony_ci            holder.end(),
38023b3eb3cSopenharmony_ci            [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
38123b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(callback);
38223b3eb3cSopenharmony_ci            }),
38323b3eb3cSopenharmony_ci        holder.end());
38423b3eb3cSopenharmony_ci}
38523b3eb3cSopenharmony_ci
38623b3eb3cSopenharmony_ci// UIObserver.on(type: "didLayout", uiContext | null, callback)
38723b3eb3cSopenharmony_ci// register a listener on current page
38823b3eb3cSopenharmony_civoid UIObserver::RegisterLayoutCallback(
38923b3eb3cSopenharmony_ci    int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
39023b3eb3cSopenharmony_ci{
39123b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
39223b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
39323b3eb3cSopenharmony_ci    }
39423b3eb3cSopenharmony_ci    if (specifiedLayoutListeners_.find(uiContextInstanceId) == specifiedLayoutListeners_.end()) {
39523b3eb3cSopenharmony_ci        specifiedLayoutListeners_[uiContextInstanceId] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
39623b3eb3cSopenharmony_ci        return;
39723b3eb3cSopenharmony_ci    }
39823b3eb3cSopenharmony_ci    auto& holder = specifiedLayoutListeners_[uiContextInstanceId];
39923b3eb3cSopenharmony_ci    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
40023b3eb3cSopenharmony_ci        return;
40123b3eb3cSopenharmony_ci    }
40223b3eb3cSopenharmony_ci    holder.emplace_back(listener);
40323b3eb3cSopenharmony_ci}
40423b3eb3cSopenharmony_ci
40523b3eb3cSopenharmony_ci// UIObserver.off(type: "didLayout", uiContext | null, callback)
40623b3eb3cSopenharmony_civoid UIObserver::UnRegisterLayoutCallback(int32_t uiContextInstanceId, napi_value callback)
40723b3eb3cSopenharmony_ci{
40823b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
40923b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
41023b3eb3cSopenharmony_ci    }
41123b3eb3cSopenharmony_ci    if (specifiedLayoutListeners_.find(uiContextInstanceId) == specifiedLayoutListeners_.end()) {
41223b3eb3cSopenharmony_ci        return;
41323b3eb3cSopenharmony_ci    }
41423b3eb3cSopenharmony_ci    auto& holder = specifiedLayoutListeners_[uiContextInstanceId];
41523b3eb3cSopenharmony_ci    if (callback == nullptr) {
41623b3eb3cSopenharmony_ci        holder.clear();
41723b3eb3cSopenharmony_ci        return;
41823b3eb3cSopenharmony_ci    }
41923b3eb3cSopenharmony_ci    holder.erase(
42023b3eb3cSopenharmony_ci        std::remove_if(
42123b3eb3cSopenharmony_ci            holder.begin(),
42223b3eb3cSopenharmony_ci            holder.end(),
42323b3eb3cSopenharmony_ci            [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
42423b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(callback);
42523b3eb3cSopenharmony_ci            }),
42623b3eb3cSopenharmony_ci        holder.end());
42723b3eb3cSopenharmony_ci}
42823b3eb3cSopenharmony_ci
42923b3eb3cSopenharmony_civoid UIObserver::HandleRouterPageStateChange(NG::AbilityContextInfo& info, const NG::RouterPageInfoNG& pageInfo)
43023b3eb3cSopenharmony_ci{
43123b3eb3cSopenharmony_ci    for (auto listenerPair : abilityContextRouterPageListeners_) {
43223b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
43323b3eb3cSopenharmony_ci        auto localInfo = infosForRouterPage_[ref];
43423b3eb3cSopenharmony_ci        if (info.IsEqual(localInfo)) {
43523b3eb3cSopenharmony_ci            auto env = GetCurrentNapiEnv();
43623b3eb3cSopenharmony_ci            napi_value abilityContext = nullptr;
43723b3eb3cSopenharmony_ci            napi_get_reference_value(env, ref, &abilityContext);
43823b3eb3cSopenharmony_ci
43923b3eb3cSopenharmony_ci            NG::RouterPageInfoNG abilityPageInfo(
44023b3eb3cSopenharmony_ci                abilityContext, pageInfo.index, pageInfo.name, pageInfo.path, pageInfo.state, pageInfo.pageId);
44123b3eb3cSopenharmony_ci            auto holder = abilityContextRouterPageListeners_[ref];
44223b3eb3cSopenharmony_ci            for (const auto& listener : holder) {
44323b3eb3cSopenharmony_ci                listener->OnRouterPageStateChange(abilityPageInfo);
44423b3eb3cSopenharmony_ci            }
44523b3eb3cSopenharmony_ci            break;
44623b3eb3cSopenharmony_ci        }
44723b3eb3cSopenharmony_ci    }
44823b3eb3cSopenharmony_ci
44923b3eb3cSopenharmony_ci    auto currentId = Container::CurrentId();
45023b3eb3cSopenharmony_ci    auto iter = specifiedRouterPageListeners_.find(currentId);
45123b3eb3cSopenharmony_ci    if (iter == specifiedRouterPageListeners_.end()) {
45223b3eb3cSopenharmony_ci        return;
45323b3eb3cSopenharmony_ci    }
45423b3eb3cSopenharmony_ci    auto holder = iter->second;
45523b3eb3cSopenharmony_ci    for (const auto& listener : holder) {
45623b3eb3cSopenharmony_ci        listener->OnRouterPageStateChange(pageInfo);
45723b3eb3cSopenharmony_ci    }
45823b3eb3cSopenharmony_ci}
45923b3eb3cSopenharmony_ci
46023b3eb3cSopenharmony_ci// UIObserver.on(type: "densityUpdate", uiContext | null, callback)
46123b3eb3cSopenharmony_ci// register a listener on current page
46223b3eb3cSopenharmony_civoid UIObserver::RegisterDensityCallback(
46323b3eb3cSopenharmony_ci    int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
46423b3eb3cSopenharmony_ci{
46523b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
46623b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
46723b3eb3cSopenharmony_ci    }
46823b3eb3cSopenharmony_ci    auto iter = specifiedDensityListeners_.find(uiContextInstanceId);
46923b3eb3cSopenharmony_ci    if (iter == specifiedDensityListeners_.end()) {
47023b3eb3cSopenharmony_ci        specifiedDensityListeners_.emplace(
47123b3eb3cSopenharmony_ci            uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
47223b3eb3cSopenharmony_ci        return;
47323b3eb3cSopenharmony_ci    }
47423b3eb3cSopenharmony_ci    auto& holder = iter->second;
47523b3eb3cSopenharmony_ci    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
47623b3eb3cSopenharmony_ci        return;
47723b3eb3cSopenharmony_ci    }
47823b3eb3cSopenharmony_ci    holder.emplace_back(listener);
47923b3eb3cSopenharmony_ci}
48023b3eb3cSopenharmony_ci
48123b3eb3cSopenharmony_ci// UIObserver.off(type: "densityUpdate", uiContext | null, callback)
48223b3eb3cSopenharmony_civoid UIObserver::UnRegisterDensityCallback(int32_t uiContextInstanceId, napi_value callback)
48323b3eb3cSopenharmony_ci{
48423b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
48523b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
48623b3eb3cSopenharmony_ci    }
48723b3eb3cSopenharmony_ci    auto iter = specifiedDensityListeners_.find(uiContextInstanceId);
48823b3eb3cSopenharmony_ci    if (iter == specifiedDensityListeners_.end()) {
48923b3eb3cSopenharmony_ci        return;
49023b3eb3cSopenharmony_ci    }
49123b3eb3cSopenharmony_ci    auto& holder = iter->second;
49223b3eb3cSopenharmony_ci    if (callback == nullptr) {
49323b3eb3cSopenharmony_ci        holder.clear();
49423b3eb3cSopenharmony_ci        return;
49523b3eb3cSopenharmony_ci    }
49623b3eb3cSopenharmony_ci    holder.erase(
49723b3eb3cSopenharmony_ci        std::remove_if(
49823b3eb3cSopenharmony_ci            holder.begin(),
49923b3eb3cSopenharmony_ci            holder.end(),
50023b3eb3cSopenharmony_ci            [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
50123b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(callback);
50223b3eb3cSopenharmony_ci            }),
50323b3eb3cSopenharmony_ci        holder.end());
50423b3eb3cSopenharmony_ci}
50523b3eb3cSopenharmony_ci
50623b3eb3cSopenharmony_civoid UIObserver::HandleDensityChange(NG::AbilityContextInfo& info, double density)
50723b3eb3cSopenharmony_ci{
50823b3eb3cSopenharmony_ci    auto currentId = Container::CurrentId();
50923b3eb3cSopenharmony_ci    auto iter = specifiedDensityListeners_.find(currentId);
51023b3eb3cSopenharmony_ci    if (iter == specifiedDensityListeners_.end()) {
51123b3eb3cSopenharmony_ci        return;
51223b3eb3cSopenharmony_ci    }
51323b3eb3cSopenharmony_ci    auto& holder = iter->second;
51423b3eb3cSopenharmony_ci    for (const auto& listener : holder) {
51523b3eb3cSopenharmony_ci        listener->OnDensityChange(density);
51623b3eb3cSopenharmony_ci    }
51723b3eb3cSopenharmony_ci}
51823b3eb3cSopenharmony_ci
51923b3eb3cSopenharmony_civoid UIObserver::HandDrawCommandSendChange()
52023b3eb3cSopenharmony_ci{
52123b3eb3cSopenharmony_ci    auto currentId = Container::CurrentId();
52223b3eb3cSopenharmony_ci    if (specifiedDrawListeners_.find(currentId) == specifiedDrawListeners_.end()) {
52323b3eb3cSopenharmony_ci        return;
52423b3eb3cSopenharmony_ci    }
52523b3eb3cSopenharmony_ci    auto& holder = specifiedDrawListeners_[currentId];
52623b3eb3cSopenharmony_ci    for (const auto& listener : holder) {
52723b3eb3cSopenharmony_ci        listener->OnDrawOrLayout();
52823b3eb3cSopenharmony_ci    }
52923b3eb3cSopenharmony_ci}
53023b3eb3cSopenharmony_ci
53123b3eb3cSopenharmony_civoid UIObserver::HandLayoutDoneChange()
53223b3eb3cSopenharmony_ci{
53323b3eb3cSopenharmony_ci    auto currentId = Container::CurrentId();
53423b3eb3cSopenharmony_ci    if (specifiedLayoutListeners_.find(currentId) == specifiedLayoutListeners_.end()) {
53523b3eb3cSopenharmony_ci        return;
53623b3eb3cSopenharmony_ci    }
53723b3eb3cSopenharmony_ci    auto& holder = specifiedLayoutListeners_[currentId];
53823b3eb3cSopenharmony_ci    for (const auto& listener : holder) {
53923b3eb3cSopenharmony_ci        listener->OnDrawOrLayout();
54023b3eb3cSopenharmony_ci    }
54123b3eb3cSopenharmony_ci}
54223b3eb3cSopenharmony_ci
54323b3eb3cSopenharmony_ci/**
54423b3eb3cSopenharmony_ci * observer.on('navDestinationSwitch', context: UIAbilityContext, callback)
54523b3eb3cSopenharmony_ci * observer.on('navDestinationSwitch', context: UIAbilityContext, { navigationId: navId }, callback)
54623b3eb3cSopenharmony_ci */
54723b3eb3cSopenharmony_civoid UIObserver::RegisterNavDestinationSwitchCallback(napi_env env, napi_value uiAbilityContext,
54823b3eb3cSopenharmony_ci    const std::optional<std::string>& navigationId, const std::shared_ptr<UIObserverListener>& listener)
54923b3eb3cSopenharmony_ci{
55023b3eb3cSopenharmony_ci    NG::AbilityContextInfo info;
55123b3eb3cSopenharmony_ci    GetAbilityInfos(env, uiAbilityContext, info);
55223b3eb3cSopenharmony_ci    for (auto& listenerPair : abilityUIContextNavDesSwitchListeners_) {
55323b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
55423b3eb3cSopenharmony_ci        auto localInfo = infosForNavDesSwitch_[ref];
55523b3eb3cSopenharmony_ci        if (!info.IsEqual(localInfo)) {
55623b3eb3cSopenharmony_ci            continue;
55723b3eb3cSopenharmony_ci        }
55823b3eb3cSopenharmony_ci
55923b3eb3cSopenharmony_ci        auto& listenersMap = listenerPair.second;
56023b3eb3cSopenharmony_ci        auto it = listenersMap.find(navigationId);
56123b3eb3cSopenharmony_ci        if (it == listenersMap.end()) {
56223b3eb3cSopenharmony_ci            listenersMap[navigationId] = std::list<std::shared_ptr<UIObserverListener>>({listener});
56323b3eb3cSopenharmony_ci            return;
56423b3eb3cSopenharmony_ci        }
56523b3eb3cSopenharmony_ci        if (std::find(it->second.begin(), it->second.end(), listener) == it->second.end()) {
56623b3eb3cSopenharmony_ci            it->second.emplace_back(listener);
56723b3eb3cSopenharmony_ci        }
56823b3eb3cSopenharmony_ci        return;
56923b3eb3cSopenharmony_ci    }
57023b3eb3cSopenharmony_ci    napi_ref newRef = nullptr;
57123b3eb3cSopenharmony_ci    napi_create_reference(env, uiAbilityContext, 1, &newRef);
57223b3eb3cSopenharmony_ci    NavIdAndListenersMap listenersMap;
57323b3eb3cSopenharmony_ci    listenersMap.emplace(navigationId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
57423b3eb3cSopenharmony_ci    abilityUIContextNavDesSwitchListeners_[newRef] = listenersMap;
57523b3eb3cSopenharmony_ci    infosForNavDesSwitch_[newRef] = info;
57623b3eb3cSopenharmony_ci}
57723b3eb3cSopenharmony_ci
57823b3eb3cSopenharmony_ci/**
57923b3eb3cSopenharmony_ci * UIObserver.on('navDestinationSwitch', { navigationId: navId }, callback)
58023b3eb3cSopenharmony_ci * UIObserver.on('navDestinationSwitch', callback)
58123b3eb3cSopenharmony_ci * observer.on('navDestinationSwitch', context: UIContext, { navigationId?: navId }, callback)
58223b3eb3cSopenharmony_ci */
58323b3eb3cSopenharmony_civoid UIObserver::RegisterNavDestinationSwitchCallback(int32_t uiContextInstanceId,
58423b3eb3cSopenharmony_ci    const std::optional<std::string>& navigationId, const std::shared_ptr<UIObserverListener>& listener)
58523b3eb3cSopenharmony_ci{
58623b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
58723b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
58823b3eb3cSopenharmony_ci    }
58923b3eb3cSopenharmony_ci    auto listenersMapIter = uiContextNavDesSwitchListeners_.find(uiContextInstanceId);
59023b3eb3cSopenharmony_ci    if (listenersMapIter == uiContextNavDesSwitchListeners_.end()) {
59123b3eb3cSopenharmony_ci        NavIdAndListenersMap listenersMap;
59223b3eb3cSopenharmony_ci        listenersMap.emplace(navigationId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
59323b3eb3cSopenharmony_ci        uiContextNavDesSwitchListeners_[uiContextInstanceId] = listenersMap;
59423b3eb3cSopenharmony_ci        return;
59523b3eb3cSopenharmony_ci    }
59623b3eb3cSopenharmony_ci
59723b3eb3cSopenharmony_ci    auto& listenersMap = listenersMapIter->second;
59823b3eb3cSopenharmony_ci    auto it = listenersMap.find(navigationId);
59923b3eb3cSopenharmony_ci    if (it == listenersMap.end()) {
60023b3eb3cSopenharmony_ci        listenersMap[navigationId] = std::list<std::shared_ptr<UIObserverListener>>({listener});
60123b3eb3cSopenharmony_ci        return;
60223b3eb3cSopenharmony_ci    }
60323b3eb3cSopenharmony_ci
60423b3eb3cSopenharmony_ci    if (std::find(it->second.begin(), it->second.end(), listener) == it->second.end()) {
60523b3eb3cSopenharmony_ci        it->second.emplace_back(listener);
60623b3eb3cSopenharmony_ci    }
60723b3eb3cSopenharmony_ci}
60823b3eb3cSopenharmony_ci
60923b3eb3cSopenharmony_ci/**
61023b3eb3cSopenharmony_ci * observer.off('navDestinationSwitch', context: AbilityUIContext})
61123b3eb3cSopenharmony_ci * observer.off('navDestinationSwitch', context: AbilityUIContext, callback })
61223b3eb3cSopenharmony_ci * observer.off('navDestinationSwitch', context: AbilityUIContext, { navigationId: navId } })
61323b3eb3cSopenharmony_ci * observer.off('navDestinationSwitch', context: AbilityUIContext, { navigationId: navId }, callback })
61423b3eb3cSopenharmony_ci */
61523b3eb3cSopenharmony_civoid UIObserver::UnRegisterNavDestinationSwitchCallback(napi_env env, napi_value uiAbilityContext,
61623b3eb3cSopenharmony_ci    const std::optional<std::string>& navigationId, napi_value callback)
61723b3eb3cSopenharmony_ci{
61823b3eb3cSopenharmony_ci    NG::AbilityContextInfo info;
61923b3eb3cSopenharmony_ci    GetAbilityInfos(env, uiAbilityContext, info);
62023b3eb3cSopenharmony_ci    for (auto listenerPair : abilityUIContextNavDesSwitchListeners_) {
62123b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
62223b3eb3cSopenharmony_ci        auto localInfo = infosForNavDesSwitch_[ref];
62323b3eb3cSopenharmony_ci        if (!info.IsEqual(localInfo)) {
62423b3eb3cSopenharmony_ci            continue;
62523b3eb3cSopenharmony_ci        }
62623b3eb3cSopenharmony_ci
62723b3eb3cSopenharmony_ci        auto& listenersMap = listenerPair.second;
62823b3eb3cSopenharmony_ci        auto it = listenersMap.find(navigationId);
62923b3eb3cSopenharmony_ci        if (it == listenersMap.end()) {
63023b3eb3cSopenharmony_ci            return;
63123b3eb3cSopenharmony_ci        }
63223b3eb3cSopenharmony_ci        auto& listeners = it->second;
63323b3eb3cSopenharmony_ci        if (callback == nullptr) {
63423b3eb3cSopenharmony_ci            listeners.clear();
63523b3eb3cSopenharmony_ci        } else {
63623b3eb3cSopenharmony_ci            listeners.erase(std::remove_if(listeners.begin(), listeners.end(),
63723b3eb3cSopenharmony_ci                [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
63823b3eb3cSopenharmony_ci                    return registeredListener->NapiEqual(callback);
63923b3eb3cSopenharmony_ci                }), listeners.end());
64023b3eb3cSopenharmony_ci        }
64123b3eb3cSopenharmony_ci        if (listeners.empty()) {
64223b3eb3cSopenharmony_ci            listenersMap.erase(it);
64323b3eb3cSopenharmony_ci        }
64423b3eb3cSopenharmony_ci        if (listenersMap.empty()) {
64523b3eb3cSopenharmony_ci            infosForNavDesSwitch_.erase(ref);
64623b3eb3cSopenharmony_ci            abilityUIContextNavDesSwitchListeners_.erase(ref);
64723b3eb3cSopenharmony_ci            napi_delete_reference(env, ref);
64823b3eb3cSopenharmony_ci        }
64923b3eb3cSopenharmony_ci        return;
65023b3eb3cSopenharmony_ci    }
65123b3eb3cSopenharmony_ci}
65223b3eb3cSopenharmony_ci
65323b3eb3cSopenharmony_ci/**
65423b3eb3cSopenharmony_ci * observer.off('navDestinationSwitch', context: UIContext})
65523b3eb3cSopenharmony_ci * observer.off('navDestinationSwitch', context: UIContext, callback })
65623b3eb3cSopenharmony_ci * observer.off('navDestinationSwitch', context: UIContext, { navigationId: navId })
65723b3eb3cSopenharmony_ci * observer.off('navDestinationSwitch', context: UIContext, { navigationId: navId }, callback )
65823b3eb3cSopenharmony_ci * UIObserver.off('navDestinationSwitch')
65923b3eb3cSopenharmony_ci * UIObserver.off('navDestinationSwitch', callback)
66023b3eb3cSopenharmony_ci * UIObserver.off('navDestinationSwitch', { navigationId: navId })
66123b3eb3cSopenharmony_ci * UIObserver.off('navDestinationSwitch', { navigationId: navId }, callback )
66223b3eb3cSopenharmony_ci */
66323b3eb3cSopenharmony_civoid UIObserver::UnRegisterNavDestinationSwitchCallback(int32_t uiContextInstanceId,
66423b3eb3cSopenharmony_ci    const std::optional<std::string>& navigationId, napi_value callback)
66523b3eb3cSopenharmony_ci{
66623b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
66723b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
66823b3eb3cSopenharmony_ci    }
66923b3eb3cSopenharmony_ci    auto listenersMapIter = uiContextNavDesSwitchListeners_.find(uiContextInstanceId);
67023b3eb3cSopenharmony_ci    if (listenersMapIter == uiContextNavDesSwitchListeners_.end()) {
67123b3eb3cSopenharmony_ci        return;
67223b3eb3cSopenharmony_ci    }
67323b3eb3cSopenharmony_ci    auto& listenersMap = listenersMapIter->second;
67423b3eb3cSopenharmony_ci    auto it = listenersMap.find(navigationId);
67523b3eb3cSopenharmony_ci    if (it == listenersMap.end()) {
67623b3eb3cSopenharmony_ci        return;
67723b3eb3cSopenharmony_ci    }
67823b3eb3cSopenharmony_ci    auto& listeners = it->second;
67923b3eb3cSopenharmony_ci    if (callback == nullptr) {
68023b3eb3cSopenharmony_ci        listeners.clear();
68123b3eb3cSopenharmony_ci    } else {
68223b3eb3cSopenharmony_ci        listeners.erase(std::remove_if(listeners.begin(), listeners.end(),
68323b3eb3cSopenharmony_ci            [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
68423b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(callback);
68523b3eb3cSopenharmony_ci            }), listeners.end());
68623b3eb3cSopenharmony_ci    }
68723b3eb3cSopenharmony_ci    if (listeners.empty()) {
68823b3eb3cSopenharmony_ci        listenersMap.erase(it);
68923b3eb3cSopenharmony_ci    }
69023b3eb3cSopenharmony_ci    if (listenersMap.empty()) {
69123b3eb3cSopenharmony_ci        uiContextNavDesSwitchListeners_.erase(listenersMapIter);
69223b3eb3cSopenharmony_ci    }
69323b3eb3cSopenharmony_ci}
69423b3eb3cSopenharmony_ci
69523b3eb3cSopenharmony_civoid UIObserver::HandleNavDestinationSwitch(
69623b3eb3cSopenharmony_ci    const NG::AbilityContextInfo& info, NG::NavDestinationSwitchInfo& switchInfo)
69723b3eb3cSopenharmony_ci{
69823b3eb3cSopenharmony_ci    HandleAbilityUIContextNavDestinationSwitch(info, switchInfo);
69923b3eb3cSopenharmony_ci    HandleUIContextNavDestinationSwitch(switchInfo);
70023b3eb3cSopenharmony_ci}
70123b3eb3cSopenharmony_ci
70223b3eb3cSopenharmony_civoid UIObserver::HandleAbilityUIContextNavDestinationSwitch(
70323b3eb3cSopenharmony_ci    const NG::AbilityContextInfo& info, NG::NavDestinationSwitchInfo& switchInfo)
70423b3eb3cSopenharmony_ci{
70523b3eb3cSopenharmony_ci    napi_value uiContextBackup = switchInfo.context;
70623b3eb3cSopenharmony_ci    for (auto listenerPair : abilityUIContextNavDesSwitchListeners_) {
70723b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
70823b3eb3cSopenharmony_ci        auto localInfo = infosForNavDesSwitch_[ref];
70923b3eb3cSopenharmony_ci        if (!info.IsEqual(localInfo)) {
71023b3eb3cSopenharmony_ci            continue;
71123b3eb3cSopenharmony_ci        }
71223b3eb3cSopenharmony_ci
71323b3eb3cSopenharmony_ci        auto env = GetCurrentNapiEnv();
71423b3eb3cSopenharmony_ci        napi_value abilityContext = nullptr;
71523b3eb3cSopenharmony_ci        napi_get_reference_value(env, ref, &abilityContext);
71623b3eb3cSopenharmony_ci
71723b3eb3cSopenharmony_ci        switchInfo.context = abilityContext;
71823b3eb3cSopenharmony_ci        auto listenersMap = listenerPair.second;
71923b3eb3cSopenharmony_ci        HandleListenersWithEmptyNavigationId(listenersMap, switchInfo);
72023b3eb3cSopenharmony_ci        HandleListenersWithSpecifiedNavigationId(listenersMap, switchInfo);
72123b3eb3cSopenharmony_ci        break;
72223b3eb3cSopenharmony_ci    }
72323b3eb3cSopenharmony_ci    switchInfo.context = uiContextBackup;
72423b3eb3cSopenharmony_ci}
72523b3eb3cSopenharmony_ci
72623b3eb3cSopenharmony_civoid UIObserver::HandleUIContextNavDestinationSwitch(const NG::NavDestinationSwitchInfo& switchInfo)
72723b3eb3cSopenharmony_ci{
72823b3eb3cSopenharmony_ci    auto currentId = Container::CurrentId();
72923b3eb3cSopenharmony_ci    auto listenersMapIter = uiContextNavDesSwitchListeners_.find(currentId);
73023b3eb3cSopenharmony_ci    if (listenersMapIter == uiContextNavDesSwitchListeners_.end()) {
73123b3eb3cSopenharmony_ci        return;
73223b3eb3cSopenharmony_ci    }
73323b3eb3cSopenharmony_ci    auto listenersMap = listenersMapIter->second;
73423b3eb3cSopenharmony_ci    HandleListenersWithEmptyNavigationId(listenersMap, switchInfo);
73523b3eb3cSopenharmony_ci    HandleListenersWithSpecifiedNavigationId(listenersMap, switchInfo);
73623b3eb3cSopenharmony_ci}
73723b3eb3cSopenharmony_ci
73823b3eb3cSopenharmony_civoid UIObserver::HandleListenersWithEmptyNavigationId(
73923b3eb3cSopenharmony_ci    const NavIdAndListenersMap& listenersMap, const NG::NavDestinationSwitchInfo& switchInfo)
74023b3eb3cSopenharmony_ci{
74123b3eb3cSopenharmony_ci    std::optional<std::string> navId;
74223b3eb3cSopenharmony_ci    auto it = listenersMap.find(navId);
74323b3eb3cSopenharmony_ci    if (it != listenersMap.end()) {
74423b3eb3cSopenharmony_ci        const auto listeners = it->second;
74523b3eb3cSopenharmony_ci        for (const auto& listener : listeners) {
74623b3eb3cSopenharmony_ci            listener->OnNavDestinationSwitch(switchInfo);
74723b3eb3cSopenharmony_ci        }
74823b3eb3cSopenharmony_ci    }
74923b3eb3cSopenharmony_ci}
75023b3eb3cSopenharmony_ci
75123b3eb3cSopenharmony_civoid UIObserver::HandleListenersWithSpecifiedNavigationId(
75223b3eb3cSopenharmony_ci    const NavIdAndListenersMap& listenersMap, const NG::NavDestinationSwitchInfo& switchInfo)
75323b3eb3cSopenharmony_ci{
75423b3eb3cSopenharmony_ci    std::string navigationId;
75523b3eb3cSopenharmony_ci    if (switchInfo.from.has_value()) {
75623b3eb3cSopenharmony_ci        navigationId = switchInfo.from.value().navigationId;
75723b3eb3cSopenharmony_ci    } else if (switchInfo.to.has_value()) {
75823b3eb3cSopenharmony_ci        navigationId = switchInfo.to.value().navigationId;
75923b3eb3cSopenharmony_ci    }
76023b3eb3cSopenharmony_ci    if (!navigationId.empty()) {
76123b3eb3cSopenharmony_ci        std::optional<std::string> navId{navigationId};
76223b3eb3cSopenharmony_ci        auto it = listenersMap.find(navId);
76323b3eb3cSopenharmony_ci        if (it != listenersMap.end()) {
76423b3eb3cSopenharmony_ci            const auto listeners = it->second;
76523b3eb3cSopenharmony_ci            for (const auto& listener : listeners) {
76623b3eb3cSopenharmony_ci                listener->OnNavDestinationSwitch(switchInfo);
76723b3eb3cSopenharmony_ci            }
76823b3eb3cSopenharmony_ci        }
76923b3eb3cSopenharmony_ci    }
77023b3eb3cSopenharmony_ci}
77123b3eb3cSopenharmony_ci
77223b3eb3cSopenharmony_civoid UIObserver::RegisterWillClickCallback(
77323b3eb3cSopenharmony_ci    napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
77423b3eb3cSopenharmony_ci{
77523b3eb3cSopenharmony_ci    napi_handle_scope scope = nullptr;
77623b3eb3cSopenharmony_ci    auto status = napi_open_handle_scope(env, &scope);
77723b3eb3cSopenharmony_ci    if (status != napi_ok) {
77823b3eb3cSopenharmony_ci        return;
77923b3eb3cSopenharmony_ci    }
78023b3eb3cSopenharmony_ci    NG::AbilityContextInfo info;
78123b3eb3cSopenharmony_ci    GetAbilityInfos(env, uiAbilityContext, info);
78223b3eb3cSopenharmony_ci    for (auto listenerPair : abilityContextWillClickListeners_) {
78323b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
78423b3eb3cSopenharmony_ci        auto localInfo = willClickInfos_[ref];
78523b3eb3cSopenharmony_ci        if (info.IsEqual(localInfo)) {
78623b3eb3cSopenharmony_ci            auto& holder = abilityContextWillClickListeners_[ref];
78723b3eb3cSopenharmony_ci            if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
78823b3eb3cSopenharmony_ci                napi_close_handle_scope(env, scope);
78923b3eb3cSopenharmony_ci                return;
79023b3eb3cSopenharmony_ci            }
79123b3eb3cSopenharmony_ci            holder.emplace_back(listener);
79223b3eb3cSopenharmony_ci            napi_close_handle_scope(env, scope);
79323b3eb3cSopenharmony_ci            return;
79423b3eb3cSopenharmony_ci        }
79523b3eb3cSopenharmony_ci    }
79623b3eb3cSopenharmony_ci    napi_ref newRef = nullptr;
79723b3eb3cSopenharmony_ci    napi_create_reference(env, uiAbilityContext, 1, &newRef);
79823b3eb3cSopenharmony_ci    abilityContextWillClickListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
79923b3eb3cSopenharmony_ci    willClickInfos_[newRef] = info;
80023b3eb3cSopenharmony_ci    napi_close_handle_scope(env, scope);
80123b3eb3cSopenharmony_ci}
80223b3eb3cSopenharmony_ci
80323b3eb3cSopenharmony_civoid UIObserver::RegisterWillClickCallback(
80423b3eb3cSopenharmony_ci    int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
80523b3eb3cSopenharmony_ci{
80623b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
80723b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
80823b3eb3cSopenharmony_ci    }
80923b3eb3cSopenharmony_ci    auto iter = specifiedWillClickListeners_.find(uiContextInstanceId);
81023b3eb3cSopenharmony_ci    if (iter == specifiedWillClickListeners_.end()) {
81123b3eb3cSopenharmony_ci        specifiedWillClickListeners_.emplace(
81223b3eb3cSopenharmony_ci            uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
81323b3eb3cSopenharmony_ci        return;
81423b3eb3cSopenharmony_ci    }
81523b3eb3cSopenharmony_ci    auto& holder = iter->second;
81623b3eb3cSopenharmony_ci    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
81723b3eb3cSopenharmony_ci        return;
81823b3eb3cSopenharmony_ci    }
81923b3eb3cSopenharmony_ci    holder.emplace_back(listener);
82023b3eb3cSopenharmony_ci}
82123b3eb3cSopenharmony_ci
82223b3eb3cSopenharmony_civoid UIObserver::UnRegisterWillClickCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
82323b3eb3cSopenharmony_ci{
82423b3eb3cSopenharmony_ci    napi_handle_scope scope = nullptr;
82523b3eb3cSopenharmony_ci    auto status = napi_open_handle_scope(env, &scope);
82623b3eb3cSopenharmony_ci    if (status != napi_ok) {
82723b3eb3cSopenharmony_ci        return;
82823b3eb3cSopenharmony_ci    }
82923b3eb3cSopenharmony_ci    NG::AbilityContextInfo info;
83023b3eb3cSopenharmony_ci    GetAbilityInfos(env, uiAbilityContext, info);
83123b3eb3cSopenharmony_ci    for (auto listenerPair : abilityContextWillClickListeners_) {
83223b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
83323b3eb3cSopenharmony_ci        auto localInfo = willClickInfos_[ref];
83423b3eb3cSopenharmony_ci        if (!info.IsEqual(localInfo)) {
83523b3eb3cSopenharmony_ci            continue;
83623b3eb3cSopenharmony_ci        }
83723b3eb3cSopenharmony_ci        auto& holder = abilityContextWillClickListeners_[listenerPair.first];
83823b3eb3cSopenharmony_ci        if (callback == nullptr) {
83923b3eb3cSopenharmony_ci            holder.clear();
84023b3eb3cSopenharmony_ci        } else {
84123b3eb3cSopenharmony_ci            holder.erase(
84223b3eb3cSopenharmony_ci                std::remove_if(
84323b3eb3cSopenharmony_ci                    holder.begin(),
84423b3eb3cSopenharmony_ci                    holder.end(),
84523b3eb3cSopenharmony_ci                    [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
84623b3eb3cSopenharmony_ci                        return registeredListener->NapiEqual(callback);
84723b3eb3cSopenharmony_ci                    }),
84823b3eb3cSopenharmony_ci                holder.end());
84923b3eb3cSopenharmony_ci        }
85023b3eb3cSopenharmony_ci        if (holder.empty()) {
85123b3eb3cSopenharmony_ci            willClickInfos_.erase(ref);
85223b3eb3cSopenharmony_ci            abilityContextWillClickListeners_.erase(ref);
85323b3eb3cSopenharmony_ci            napi_delete_reference(env, ref);
85423b3eb3cSopenharmony_ci        }
85523b3eb3cSopenharmony_ci    }
85623b3eb3cSopenharmony_ci    napi_close_handle_scope(env, scope);
85723b3eb3cSopenharmony_ci}
85823b3eb3cSopenharmony_ci
85923b3eb3cSopenharmony_civoid UIObserver::UnRegisterWillClickCallback(int32_t uiContextInstanceId, napi_value callback)
86023b3eb3cSopenharmony_ci{
86123b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
86223b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
86323b3eb3cSopenharmony_ci    }
86423b3eb3cSopenharmony_ci    auto iter = specifiedWillClickListeners_.find(uiContextInstanceId);
86523b3eb3cSopenharmony_ci    if (iter == specifiedWillClickListeners_.end()) {
86623b3eb3cSopenharmony_ci        return;
86723b3eb3cSopenharmony_ci    }
86823b3eb3cSopenharmony_ci    auto& holder = iter->second;
86923b3eb3cSopenharmony_ci    if (callback == nullptr) {
87023b3eb3cSopenharmony_ci        holder.clear();
87123b3eb3cSopenharmony_ci        return;
87223b3eb3cSopenharmony_ci    }
87323b3eb3cSopenharmony_ci    holder.erase(
87423b3eb3cSopenharmony_ci        std::remove_if(
87523b3eb3cSopenharmony_ci            holder.begin(),
87623b3eb3cSopenharmony_ci            holder.end(),
87723b3eb3cSopenharmony_ci            [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
87823b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(callback);
87923b3eb3cSopenharmony_ci            }),
88023b3eb3cSopenharmony_ci        holder.end());
88123b3eb3cSopenharmony_ci}
88223b3eb3cSopenharmony_ci
88323b3eb3cSopenharmony_civoid UIObserver::HandleWillClick(NG::AbilityContextInfo& info, const GestureEvent& gestureEventInfo,
88423b3eb3cSopenharmony_ci    const ClickInfo& clickInfo, const RefPtr<NG::FrameNode>& frameNode)
88523b3eb3cSopenharmony_ci{
88623b3eb3cSopenharmony_ci    auto env = GetCurrentNapiEnv();
88723b3eb3cSopenharmony_ci    napi_handle_scope scope = nullptr;
88823b3eb3cSopenharmony_ci    auto status = napi_open_handle_scope(env, &scope);
88923b3eb3cSopenharmony_ci    if (status != napi_ok) {
89023b3eb3cSopenharmony_ci        return;
89123b3eb3cSopenharmony_ci    }
89223b3eb3cSopenharmony_ci    for (auto listenerPair : abilityContextWillClickListeners_) {
89323b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
89423b3eb3cSopenharmony_ci        auto localInfo = willClickInfos_[ref];
89523b3eb3cSopenharmony_ci        if (info.IsEqual(localInfo)) {
89623b3eb3cSopenharmony_ci            napi_value abilityContext = nullptr;
89723b3eb3cSopenharmony_ci            napi_get_reference_value(env, ref, &abilityContext);
89823b3eb3cSopenharmony_ci
89923b3eb3cSopenharmony_ci            auto& holder = abilityContextWillClickListeners_[ref];
90023b3eb3cSopenharmony_ci            for (const auto& listener : holder) {
90123b3eb3cSopenharmony_ci                listener->OnWillClick(gestureEventInfo, clickInfo, frameNode);
90223b3eb3cSopenharmony_ci            }
90323b3eb3cSopenharmony_ci            break;
90423b3eb3cSopenharmony_ci        }
90523b3eb3cSopenharmony_ci    }
90623b3eb3cSopenharmony_ci
90723b3eb3cSopenharmony_ci    auto currentId = Container::CurrentId();
90823b3eb3cSopenharmony_ci    auto iter = specifiedWillClickListeners_.find(currentId);
90923b3eb3cSopenharmony_ci    if (iter == specifiedWillClickListeners_.end()) {
91023b3eb3cSopenharmony_ci        napi_close_handle_scope(env, scope);
91123b3eb3cSopenharmony_ci        return;
91223b3eb3cSopenharmony_ci    }
91323b3eb3cSopenharmony_ci    auto& holder = iter->second;
91423b3eb3cSopenharmony_ci    for (const auto& listener : holder) {
91523b3eb3cSopenharmony_ci        listener->OnWillClick(gestureEventInfo, clickInfo, frameNode);
91623b3eb3cSopenharmony_ci    }
91723b3eb3cSopenharmony_ci    napi_close_handle_scope(env, scope);
91823b3eb3cSopenharmony_ci}
91923b3eb3cSopenharmony_ci
92023b3eb3cSopenharmony_civoid UIObserver::RegisterDidClickCallback(
92123b3eb3cSopenharmony_ci    napi_env env, napi_value uiAbilityContext, const std::shared_ptr<UIObserverListener>& listener)
92223b3eb3cSopenharmony_ci{
92323b3eb3cSopenharmony_ci    napi_handle_scope scope = nullptr;
92423b3eb3cSopenharmony_ci    auto status = napi_open_handle_scope(env, &scope);
92523b3eb3cSopenharmony_ci    if (status != napi_ok) {
92623b3eb3cSopenharmony_ci        return;
92723b3eb3cSopenharmony_ci    }
92823b3eb3cSopenharmony_ci    NG::AbilityContextInfo info;
92923b3eb3cSopenharmony_ci    GetAbilityInfos(env, uiAbilityContext, info);
93023b3eb3cSopenharmony_ci    for (auto listenerPair : abilityContextDidClickListeners_) {
93123b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
93223b3eb3cSopenharmony_ci        auto localInfo = didClickInfos_[ref];
93323b3eb3cSopenharmony_ci        if (info.IsEqual(localInfo)) {
93423b3eb3cSopenharmony_ci            auto& holder = abilityContextDidClickListeners_[ref];
93523b3eb3cSopenharmony_ci            if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
93623b3eb3cSopenharmony_ci                napi_close_handle_scope(env, scope);
93723b3eb3cSopenharmony_ci                return;
93823b3eb3cSopenharmony_ci            }
93923b3eb3cSopenharmony_ci            holder.emplace_back(listener);
94023b3eb3cSopenharmony_ci            napi_close_handle_scope(env, scope);
94123b3eb3cSopenharmony_ci            return;
94223b3eb3cSopenharmony_ci        }
94323b3eb3cSopenharmony_ci    }
94423b3eb3cSopenharmony_ci    napi_ref newRef = nullptr;
94523b3eb3cSopenharmony_ci    napi_create_reference(env, uiAbilityContext, 1, &newRef);
94623b3eb3cSopenharmony_ci    abilityContextDidClickListeners_[newRef] = std::list<std::shared_ptr<UIObserverListener>>({ listener });
94723b3eb3cSopenharmony_ci    didClickInfos_[newRef] = info;
94823b3eb3cSopenharmony_ci    napi_close_handle_scope(env, scope);
94923b3eb3cSopenharmony_ci}
95023b3eb3cSopenharmony_ci
95123b3eb3cSopenharmony_civoid UIObserver::RegisterDidClickCallback(
95223b3eb3cSopenharmony_ci    int32_t uiContextInstanceId, const std::shared_ptr<UIObserverListener>& listener)
95323b3eb3cSopenharmony_ci{
95423b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
95523b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
95623b3eb3cSopenharmony_ci    }
95723b3eb3cSopenharmony_ci    auto iter = specifiedDidClickListeners_.find(uiContextInstanceId);
95823b3eb3cSopenharmony_ci    if (iter == specifiedDidClickListeners_.end()) {
95923b3eb3cSopenharmony_ci        specifiedDidClickListeners_.emplace(
96023b3eb3cSopenharmony_ci            uiContextInstanceId, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
96123b3eb3cSopenharmony_ci        return;
96223b3eb3cSopenharmony_ci    }
96323b3eb3cSopenharmony_ci    auto& holder = iter->second;
96423b3eb3cSopenharmony_ci    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
96523b3eb3cSopenharmony_ci        return;
96623b3eb3cSopenharmony_ci    }
96723b3eb3cSopenharmony_ci    holder.emplace_back(listener);
96823b3eb3cSopenharmony_ci}
96923b3eb3cSopenharmony_ci
97023b3eb3cSopenharmony_civoid UIObserver::UnRegisterDidClickCallback(napi_env env, napi_value uiAbilityContext, napi_value callback)
97123b3eb3cSopenharmony_ci{
97223b3eb3cSopenharmony_ci    napi_handle_scope scope = nullptr;
97323b3eb3cSopenharmony_ci    auto status = napi_open_handle_scope(env, &scope);
97423b3eb3cSopenharmony_ci    if (status != napi_ok) {
97523b3eb3cSopenharmony_ci        return;
97623b3eb3cSopenharmony_ci    }
97723b3eb3cSopenharmony_ci    NG::AbilityContextInfo info;
97823b3eb3cSopenharmony_ci    GetAbilityInfos(env, uiAbilityContext, info);
97923b3eb3cSopenharmony_ci    for (auto listenerPair : abilityContextDidClickListeners_) {
98023b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
98123b3eb3cSopenharmony_ci        auto localInfo = didClickInfos_[ref];
98223b3eb3cSopenharmony_ci        if (!info.IsEqual(localInfo)) {
98323b3eb3cSopenharmony_ci            continue;
98423b3eb3cSopenharmony_ci        }
98523b3eb3cSopenharmony_ci        auto& holder = abilityContextDidClickListeners_[listenerPair.first];
98623b3eb3cSopenharmony_ci        if (callback == nullptr) {
98723b3eb3cSopenharmony_ci            holder.clear();
98823b3eb3cSopenharmony_ci        } else {
98923b3eb3cSopenharmony_ci            holder.erase(
99023b3eb3cSopenharmony_ci                std::remove_if(
99123b3eb3cSopenharmony_ci                    holder.begin(),
99223b3eb3cSopenharmony_ci                    holder.end(),
99323b3eb3cSopenharmony_ci                    [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
99423b3eb3cSopenharmony_ci                        return registeredListener->NapiEqual(callback);
99523b3eb3cSopenharmony_ci                    }),
99623b3eb3cSopenharmony_ci                holder.end());
99723b3eb3cSopenharmony_ci        }
99823b3eb3cSopenharmony_ci        if (holder.empty()) {
99923b3eb3cSopenharmony_ci            didClickInfos_.erase(ref);
100023b3eb3cSopenharmony_ci            abilityContextDidClickListeners_.erase(ref);
100123b3eb3cSopenharmony_ci            napi_delete_reference(env, ref);
100223b3eb3cSopenharmony_ci        }
100323b3eb3cSopenharmony_ci    }
100423b3eb3cSopenharmony_ci    napi_close_handle_scope(env, scope);
100523b3eb3cSopenharmony_ci}
100623b3eb3cSopenharmony_ci
100723b3eb3cSopenharmony_civoid UIObserver::UnRegisterDidClickCallback(int32_t uiContextInstanceId, napi_value callback)
100823b3eb3cSopenharmony_ci{
100923b3eb3cSopenharmony_ci    if (uiContextInstanceId == 0) {
101023b3eb3cSopenharmony_ci        uiContextInstanceId = Container::CurrentId();
101123b3eb3cSopenharmony_ci    }
101223b3eb3cSopenharmony_ci    auto iter = specifiedDidClickListeners_.find(uiContextInstanceId);
101323b3eb3cSopenharmony_ci    if (iter == specifiedDidClickListeners_.end()) {
101423b3eb3cSopenharmony_ci        return;
101523b3eb3cSopenharmony_ci    }
101623b3eb3cSopenharmony_ci    auto& holder = iter->second;
101723b3eb3cSopenharmony_ci    if (callback == nullptr) {
101823b3eb3cSopenharmony_ci        holder.clear();
101923b3eb3cSopenharmony_ci        return;
102023b3eb3cSopenharmony_ci    }
102123b3eb3cSopenharmony_ci    holder.erase(
102223b3eb3cSopenharmony_ci        std::remove_if(
102323b3eb3cSopenharmony_ci            holder.begin(),
102423b3eb3cSopenharmony_ci            holder.end(),
102523b3eb3cSopenharmony_ci            [callback](const std::shared_ptr<UIObserverListener>& registeredListener) {
102623b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(callback);
102723b3eb3cSopenharmony_ci            }),
102823b3eb3cSopenharmony_ci        holder.end());
102923b3eb3cSopenharmony_ci}
103023b3eb3cSopenharmony_ci
103123b3eb3cSopenharmony_civoid UIObserver::HandleDidClick(NG::AbilityContextInfo& info, const GestureEvent& gestureEventInfo,
103223b3eb3cSopenharmony_ci    const ClickInfo& clickInfo, const RefPtr<NG::FrameNode>& frameNode)
103323b3eb3cSopenharmony_ci{
103423b3eb3cSopenharmony_ci    auto env = GetCurrentNapiEnv();
103523b3eb3cSopenharmony_ci    napi_handle_scope scope = nullptr;
103623b3eb3cSopenharmony_ci    auto status = napi_open_handle_scope(env, &scope);
103723b3eb3cSopenharmony_ci    if (status != napi_ok) {
103823b3eb3cSopenharmony_ci        return;
103923b3eb3cSopenharmony_ci    }
104023b3eb3cSopenharmony_ci    for (auto listenerPair : abilityContextDidClickListeners_) {
104123b3eb3cSopenharmony_ci        auto ref = listenerPair.first;
104223b3eb3cSopenharmony_ci        auto localInfo = didClickInfos_[ref];
104323b3eb3cSopenharmony_ci        if (info.IsEqual(localInfo)) {
104423b3eb3cSopenharmony_ci            napi_value abilityContext = nullptr;
104523b3eb3cSopenharmony_ci            napi_get_reference_value(env, ref, &abilityContext);
104623b3eb3cSopenharmony_ci
104723b3eb3cSopenharmony_ci            auto& holder = abilityContextDidClickListeners_[ref];
104823b3eb3cSopenharmony_ci            for (const auto& listener : holder) {
104923b3eb3cSopenharmony_ci                listener->OnDidClick(gestureEventInfo, clickInfo, frameNode);
105023b3eb3cSopenharmony_ci            }
105123b3eb3cSopenharmony_ci            break;
105223b3eb3cSopenharmony_ci        }
105323b3eb3cSopenharmony_ci    }
105423b3eb3cSopenharmony_ci
105523b3eb3cSopenharmony_ci    auto currentId = Container::CurrentId();
105623b3eb3cSopenharmony_ci    auto iter = specifiedDidClickListeners_.find(currentId);
105723b3eb3cSopenharmony_ci    if (iter == specifiedDidClickListeners_.end()) {
105823b3eb3cSopenharmony_ci        napi_close_handle_scope(env, scope);
105923b3eb3cSopenharmony_ci        return;
106023b3eb3cSopenharmony_ci    }
106123b3eb3cSopenharmony_ci    auto& holder = iter->second;
106223b3eb3cSopenharmony_ci    for (const auto& listener : holder) {
106323b3eb3cSopenharmony_ci        listener->OnDidClick(gestureEventInfo, clickInfo, frameNode);
106423b3eb3cSopenharmony_ci    }
106523b3eb3cSopenharmony_ci    napi_close_handle_scope(env, scope);
106623b3eb3cSopenharmony_ci}
106723b3eb3cSopenharmony_ci
106823b3eb3cSopenharmony_ci// UIObserver.on(type: "tabContentState", callback)
106923b3eb3cSopenharmony_ci// register a global listener without options
107023b3eb3cSopenharmony_civoid UIObserver::RegisterTabContentStateCallback(const std::shared_ptr<UIObserverListener>& listener)
107123b3eb3cSopenharmony_ci{
107223b3eb3cSopenharmony_ci    if (std::find(tabContentStateListeners_.begin(), tabContentStateListeners_.end(), listener) !=
107323b3eb3cSopenharmony_ci        tabContentStateListeners_.end()) {
107423b3eb3cSopenharmony_ci        return;
107523b3eb3cSopenharmony_ci    }
107623b3eb3cSopenharmony_ci    tabContentStateListeners_.emplace_back(listener);
107723b3eb3cSopenharmony_ci}
107823b3eb3cSopenharmony_ci
107923b3eb3cSopenharmony_ci// UIObserver.on(type: "tabContentState", options, callback)
108023b3eb3cSopenharmony_ci// register a listener on a specified tabContentState
108123b3eb3cSopenharmony_civoid UIObserver::RegisterTabContentStateCallback(
108223b3eb3cSopenharmony_ci    const std::string& id, const std::shared_ptr<UIObserverListener>& listener)
108323b3eb3cSopenharmony_ci{
108423b3eb3cSopenharmony_ci    auto iter = specifiedTabContentStateListeners_.find(id);
108523b3eb3cSopenharmony_ci    if (iter == specifiedTabContentStateListeners_.end()) {
108623b3eb3cSopenharmony_ci        specifiedTabContentStateListeners_.emplace(id, std::list<std::shared_ptr<UIObserverListener>>({ listener }));
108723b3eb3cSopenharmony_ci        return;
108823b3eb3cSopenharmony_ci    }
108923b3eb3cSopenharmony_ci    auto& holder = iter->second;
109023b3eb3cSopenharmony_ci    if (std::find(holder.begin(), holder.end(), listener) != holder.end()) {
109123b3eb3cSopenharmony_ci        return;
109223b3eb3cSopenharmony_ci    }
109323b3eb3cSopenharmony_ci    holder.emplace_back(listener);
109423b3eb3cSopenharmony_ci}
109523b3eb3cSopenharmony_ci
109623b3eb3cSopenharmony_ci// UIObserver.off(type: "tabContentState", callback)
109723b3eb3cSopenharmony_civoid UIObserver::UnRegisterTabContentStateCallback(napi_value cb)
109823b3eb3cSopenharmony_ci{
109923b3eb3cSopenharmony_ci    if (cb == nullptr) {
110023b3eb3cSopenharmony_ci        tabContentStateListeners_.clear();
110123b3eb3cSopenharmony_ci        return;
110223b3eb3cSopenharmony_ci    }
110323b3eb3cSopenharmony_ci
110423b3eb3cSopenharmony_ci    tabContentStateListeners_.erase(
110523b3eb3cSopenharmony_ci        std::remove_if(
110623b3eb3cSopenharmony_ci            tabContentStateListeners_.begin(),
110723b3eb3cSopenharmony_ci            tabContentStateListeners_.end(),
110823b3eb3cSopenharmony_ci            [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
110923b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(cb);
111023b3eb3cSopenharmony_ci            }),
111123b3eb3cSopenharmony_ci        tabContentStateListeners_.end()
111223b3eb3cSopenharmony_ci    );
111323b3eb3cSopenharmony_ci}
111423b3eb3cSopenharmony_ci
111523b3eb3cSopenharmony_ci// UIObserver.off(type: "tabContentState", options, callback)
111623b3eb3cSopenharmony_civoid UIObserver::UnRegisterTabContentStateCallback(const std::string& id, napi_value cb)
111723b3eb3cSopenharmony_ci{
111823b3eb3cSopenharmony_ci    auto iter = specifiedTabContentStateListeners_.find(id);
111923b3eb3cSopenharmony_ci    if (iter == specifiedTabContentStateListeners_.end()) {
112023b3eb3cSopenharmony_ci        return;
112123b3eb3cSopenharmony_ci    }
112223b3eb3cSopenharmony_ci    auto& holder = iter->second;
112323b3eb3cSopenharmony_ci    if (cb == nullptr) {
112423b3eb3cSopenharmony_ci        holder.clear();
112523b3eb3cSopenharmony_ci        return;
112623b3eb3cSopenharmony_ci    }
112723b3eb3cSopenharmony_ci    holder.erase(
112823b3eb3cSopenharmony_ci        std::remove_if(
112923b3eb3cSopenharmony_ci            holder.begin(),
113023b3eb3cSopenharmony_ci            holder.end(),
113123b3eb3cSopenharmony_ci            [cb](const std::shared_ptr<UIObserverListener>& registeredListener) {
113223b3eb3cSopenharmony_ci                return registeredListener->NapiEqual(cb);
113323b3eb3cSopenharmony_ci            }),
113423b3eb3cSopenharmony_ci        holder.end()
113523b3eb3cSopenharmony_ci    );
113623b3eb3cSopenharmony_ci}
113723b3eb3cSopenharmony_ci
113823b3eb3cSopenharmony_civoid UIObserver::HandleTabContentStateChange(const NG::TabContentInfo& tabContentInfo)
113923b3eb3cSopenharmony_ci{
114023b3eb3cSopenharmony_ci    for (const auto& listener : tabContentStateListeners_) {
114123b3eb3cSopenharmony_ci        listener->OnTabContentStateChange(tabContentInfo);
114223b3eb3cSopenharmony_ci    }
114323b3eb3cSopenharmony_ci
114423b3eb3cSopenharmony_ci    auto iter = specifiedTabContentStateListeners_.find(tabContentInfo.id);
114523b3eb3cSopenharmony_ci    if (iter == specifiedTabContentStateListeners_.end()) {
114623b3eb3cSopenharmony_ci        return;
114723b3eb3cSopenharmony_ci    }
114823b3eb3cSopenharmony_ci
114923b3eb3cSopenharmony_ci    auto& holder = iter->second;
115023b3eb3cSopenharmony_ci
115123b3eb3cSopenharmony_ci    for (const auto& listener : holder) {
115223b3eb3cSopenharmony_ci        listener->OnTabContentStateChange(tabContentInfo);
115323b3eb3cSopenharmony_ci    }
115423b3eb3cSopenharmony_ci}
115523b3eb3cSopenharmony_ci
115623b3eb3cSopenharmony_civoid UIObserver::GetAbilityInfos(napi_env env, napi_value abilityContext, NG::AbilityContextInfo& info)
115723b3eb3cSopenharmony_ci{
115823b3eb3cSopenharmony_ci    if (!env || !abilityContext) {
115923b3eb3cSopenharmony_ci        return;
116023b3eb3cSopenharmony_ci    }
116123b3eb3cSopenharmony_ci    napi_value napiInfo = nullptr;
116223b3eb3cSopenharmony_ci    napi_get_named_property(env, abilityContext, "abilityInfo", &napiInfo);
116323b3eb3cSopenharmony_ci    CHECK_NULL_VOID(napiInfo);
116423b3eb3cSopenharmony_ci    napi_value name = nullptr;
116523b3eb3cSopenharmony_ci    napi_get_named_property(env, napiInfo, "name", &name);
116623b3eb3cSopenharmony_ci    ParseStringFromNapi(env, name, info.name);
116723b3eb3cSopenharmony_ci    napi_get_named_property(env, napiInfo, "bundleName", &name);
116823b3eb3cSopenharmony_ci    ParseStringFromNapi(env, name, info.bundleName);
116923b3eb3cSopenharmony_ci    napi_get_named_property(env, napiInfo, "moduleName", &name);
117023b3eb3cSopenharmony_ci    ParseStringFromNapi(env, name, info.moduleName);
117123b3eb3cSopenharmony_ci}
117223b3eb3cSopenharmony_ci
117323b3eb3cSopenharmony_cibool UIObserver::ParseStringFromNapi(napi_env env, napi_value val, std::string& str)
117423b3eb3cSopenharmony_ci{
117523b3eb3cSopenharmony_ci    if (!val || !MatchValueType(env, val, napi_string)) {
117623b3eb3cSopenharmony_ci        return false;
117723b3eb3cSopenharmony_ci    }
117823b3eb3cSopenharmony_ci    size_t len = 0;
117923b3eb3cSopenharmony_ci    napi_get_value_string_utf8(env, val, nullptr, 0, &len);
118023b3eb3cSopenharmony_ci    std::unique_ptr<char[]> result = std::make_unique<char[]>(len + 1);
118123b3eb3cSopenharmony_ci    napi_get_value_string_utf8(env, val, result.get(), len + 1, &len);
118223b3eb3cSopenharmony_ci    str = result.get();
118323b3eb3cSopenharmony_ci    return true;
118423b3eb3cSopenharmony_ci}
118523b3eb3cSopenharmony_ci
118623b3eb3cSopenharmony_cibool UIObserver::MatchValueType(napi_env env, napi_value value, napi_valuetype targetType)
118723b3eb3cSopenharmony_ci{
118823b3eb3cSopenharmony_ci    napi_valuetype valueType = napi_undefined;
118923b3eb3cSopenharmony_ci    napi_typeof(env, value, &valueType);
119023b3eb3cSopenharmony_ci    return valueType == targetType;
119123b3eb3cSopenharmony_ci}
119223b3eb3cSopenharmony_ci
119323b3eb3cSopenharmony_cinapi_env UIObserver::GetCurrentNapiEnv()
119423b3eb3cSopenharmony_ci{
119523b3eb3cSopenharmony_ci    auto engine = EngineHelper::GetCurrentEngine();
119623b3eb3cSopenharmony_ci    CHECK_NULL_RETURN(engine, nullptr);
119723b3eb3cSopenharmony_ci    NativeEngine* nativeEngine = engine->GetNativeEngine();
119823b3eb3cSopenharmony_ci    CHECK_NULL_RETURN(nativeEngine, nullptr);
119923b3eb3cSopenharmony_ci    return reinterpret_cast<napi_env>(nativeEngine);
120023b3eb3cSopenharmony_ci}
120123b3eb3cSopenharmony_ci} // namespace OHOS::Ace::Napi
1202