1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "frameworks/bridge/declarative_frontend/jsview/js_app_bar_view.h"
17
18 #include <cstdint>
19
20 #include "ui/base/utils/utils.h"
21
22 #include "base/memory/ace_type.h"
23 #include "base/utils/utils.h"
24 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_common_bridge.h"
25 #include "core/common/ace_engine.h"
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/pattern/container_modal/enhance/container_modal_pattern_enhance.h"
28 #include "core/pipeline_ng/pipeline_context.h"
29
30 namespace OHOS::Ace::Framework {
31 namespace {
32 const std::string EVENT_NAME_CUSTOM_APP_BAR_MENU_CLICK = "arkui_custom_app_bar_menu_click";
33 const std::string EVENT_NAME_CUSTOM_APP_BAR_CLOSE_CLICK = "arkui_custom_app_bar_close_click";
34 const std::string EVENT_NAME_CUSTOM_APP_BAR_DID_BUILD = "arkui_custom_app_bar_did_build";
35 const std::string EVENT_NAME_CUSTOM_APP_BAR_CREATE_SERVICE_PANEL = "arkui_custom_app_bar_create_service_panel";
36
37 constexpr int32_t SERVICE_PANEL_PARAM_COUNT = 2;
38 constexpr int32_t PARAM_FIRST = 1;
39
40 static std::map<std::string, std::function<void(const JSCallbackInfo& info)>> nativeFucMap_;
41 } // namespace
42
OnMenuClick(const JSCallbackInfo & info)43 void JSAppBar::OnMenuClick(const JSCallbackInfo& info)
44 {
45 TAG_LOGI(AceLogTag::ACE_APPBAR, "JSAppBar OnMenuClick");
46 auto container = Container::Current();
47 CHECK_NULL_VOID(container);
48 auto appBar = container->GetAppBar();
49 CHECK_NULL_VOID(appBar);
50 appBar->OnMenuClick();
51 }
52
OnCloseClick(const JSCallbackInfo & info)53 void JSAppBar::OnCloseClick(const JSCallbackInfo& info)
54 {
55 TAG_LOGI(AceLogTag::ACE_APPBAR, "JSAppBar OnCloseClick");
56 auto container = Container::Current();
57 CHECK_NULL_VOID(container);
58 auto appBar = container->GetAppBar();
59 CHECK_NULL_VOID(appBar);
60 appBar->OnCloseClick();
61 }
62
OnDidBuild(const JSCallbackInfo & info)63 void JSAppBar::OnDidBuild(const JSCallbackInfo& info)
64 {
65 TAG_LOGI(AceLogTag::ACE_APPBAR, "JSAppBar OnDidBuild");
66 auto container = Container::Current();
67 CHECK_NULL_VOID(container);
68 auto appBar = container->GetAppBar();
69 CHECK_NULL_VOID(appBar);
70 }
71
OnCreateServicePanel(const JSCallbackInfo & info)72 void JSAppBar::OnCreateServicePanel(const JSCallbackInfo& info)
73 {
74 TAG_LOGI(AceLogTag::ACE_APPBAR, "JSAppBar OnCreateServicePanel");
75
76 if (info.Length() < SERVICE_PANEL_PARAM_COUNT) {
77 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar OnCreateServicePanel param erro");
78 return;
79 }
80 if (!info[PARAM_FIRST]->IsObject()) {
81 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar OnCreateServicePanel last param erro");
82 return;
83 }
84 JSRef<JSObject> jsObject = JSRef<JSObject>::Cast(info[PARAM_FIRST]);
85 auto bundleName = GetStringValueFromJSObject(jsObject, "bundleName");
86 if (bundleName.empty()) {
87 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar GetStringValueFromJSObject bundleName param is error");
88 return;
89 }
90
91 auto abilityName = GetStringValueFromJSObject(jsObject, "abilityName");
92 if (abilityName.empty()) {
93 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar GetStringValueFromJSObject abilityName param is error");
94 return;
95 }
96
97 auto jsParams = jsObject->GetProperty("params");
98 if (!jsParams->IsArray()) {
99 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar GetStringValueFromJSObject jsParams is error");
100 return;
101 }
102 JSRef<JSArray> jsParamsArray = JSRef<JSArray>::Cast(jsParams);
103 std::map<std::string, std::string> params;
104 GetParamsFromJSArray(jsParamsArray, params);
105 if (params.empty()) {
106 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar GetStringValueFromJSObject paramsMap param is error");
107 return;
108 }
109 auto container = Container::Current();
110 CHECK_NULL_VOID(container);
111 auto appBar = container->GetAppBar();
112 CHECK_NULL_VOID(appBar);
113 appBar->CreateServicePanel(bundleName, abilityName, params);
114 }
115
GetStringValueFromJSObject(const JSRef<JSObject> & object,const char * prop)116 std::string JSAppBar::GetStringValueFromJSObject(const JSRef<JSObject>& object, const char* prop)
117 {
118 auto jsValue = object->GetProperty(prop);
119 if (!jsValue->IsString()) {
120 return "";
121 }
122 return jsValue->ToString();
123 }
124
GetParamsFromJSArray(const JSRef<JSArray> & jsArray,std::map<std::string,std::string> & params)125 void JSAppBar::GetParamsFromJSArray(const JSRef<JSArray>& jsArray, std::map<std::string, std::string>& params)
126 {
127 int length = static_cast<int>(jsArray->Length());
128 for (int i = 0; i < length; i++) {
129 JSRef<JSVal> jsValue = jsArray->GetValueAt(i);
130 if (!jsValue->IsString()) {
131 continue;
132 }
133 auto pair = jsValue->ToString();
134 size_t colonPos = pair.find(':');
135 if (colonPos == std::string::npos) {
136 continue;
137 }
138 std::string key = pair.substr(0, colonPos);
139 std::string value = pair.substr(colonPos + 1);
140 if (key.empty() || value.empty()) {
141 continue;
142 }
143 params[key] = value;
144 }
145 }
146
CallNative(const JSCallbackInfo & info)147 void JSAppBar::CallNative(const JSCallbackInfo& info)
148 {
149 nativeFucMap_ = {
150 { EVENT_NAME_CUSTOM_APP_BAR_MENU_CLICK, JSAppBar::OnMenuClick },
151 { EVENT_NAME_CUSTOM_APP_BAR_CLOSE_CLICK, JSAppBar::OnCloseClick },
152 { EVENT_NAME_CUSTOM_APP_BAR_DID_BUILD, JSAppBar::OnDidBuild },
153 { EVENT_NAME_CUSTOM_APP_BAR_CREATE_SERVICE_PANEL, JSAppBar::OnCreateServicePanel },
154 };
155
156 if (info.Length() < 1) {
157 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar callNative param erro");
158 return;
159 }
160 if (!info[0]->IsString()) {
161 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar callNative first param erro");
162 return;
163 }
164 std::string eventName = info[0]->ToString();
165 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar callNative eventName = %{public}s", eventName.c_str());
166 auto it = nativeFucMap_.find(eventName);
167 if (it == nativeFucMap_.end()) {
168 TAG_LOGI(AceLogTag::ACE_APPBAR, "appbar Event not found: %{public}s", eventName.c_str());
169 return;
170 }
171 it->second(info);
172 }
173
JSBind(BindingTarget globalObj)174 void JSAppBar::JSBind(BindingTarget globalObj)
175 {
176 JSClass<JSAppBar>::Declare("ContainerAppBar");
177 JSClass<JSAppBar>::StaticMethod("callNative", &JSAppBar::CallNative);
178 JSClass<JSAppBar>::InheritAndBind<JSContainerBase>(globalObj);
179 }
180 } // namespace OHOS::Ace::Framework
181