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