1 /*
2 * Copyright (c) 2021-2022 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_interactable_view.h"
17
18 #include "base/log/ace_scoring_log.h"
19 #include "base/log/log_wrapper.h"
20 #include "bridge/declarative_frontend/engine/functions/js_click_function.h"
21 #include "bridge/declarative_frontend/engine/functions/js_hover_function.h"
22 #include "bridge/declarative_frontend/engine/functions/js_key_function.h"
23 #include "bridge/declarative_frontend/engine/js_execution_scope_defines.h"
24 #include "bridge/declarative_frontend/jsview/js_pan_handler.h"
25 #include "bridge/declarative_frontend/jsview/js_touch_handler.h"
26 #include "bridge/declarative_frontend/jsview/js_utils.h"
27 #include "bridge/declarative_frontend/view_stack_processor.h"
28 #include "core/common/container.h"
29 #include "core/components/gesture_listener/gesture_listener_component.h"
30 #include "core/components_ng/base/view_abstract_model.h"
31 #include "core/gestures/click_recognizer.h"
32 #include "core/pipeline/base/single_child.h"
33
34 #ifdef PLUGIN_COMPONENT_SUPPORTED
35 #include "core/common/plugin_manager.h"
36 #endif
37
38 namespace OHOS::Ace::Framework {
39
JsOnTouch(const JSCallbackInfo & args)40 void JSInteractableView::JsOnTouch(const JSCallbackInfo& args)
41 {
42 LOGD("JSInteractableView JsOnTouch");
43 if (args[0]->IsUndefined() && IsDisableEventVersion()) {
44 LOGD("JsOnTouch callback is undefined");
45 ViewAbstractModel::GetInstance()->DisableOnTouch();
46 return;
47 }
48 if (!args[0]->IsFunction()) {
49 LOGW("the info is not touch function");
50 return;
51 }
52 RefPtr<JsTouchFunction> jsOnTouchFunc = AceType::MakeRefPtr<JsTouchFunction>(JSRef<JSFunc>::Cast(args[0]));
53 auto onTouch = [execCtx = args.GetExecutionContext(), func = std::move(jsOnTouchFunc)](TouchEventInfo& info) {
54 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
55 ACE_SCORING_EVENT("onTouch");
56 func->Execute(info);
57 };
58 ViewAbstractModel::GetInstance()->SetOnTouch(std::move(onTouch));
59 }
60
JsOnKey(const JSCallbackInfo & args)61 void JSInteractableView::JsOnKey(const JSCallbackInfo& args)
62 {
63 LOGD("JSInteractableView JsOnKey");
64 if (args[0]->IsUndefined() && IsDisableEventVersion()) {
65 LOGD("JsOnKey callback is undefined");
66 ViewAbstractModel::GetInstance()->DisableOnKeyEvent();
67 return;
68 }
69 if (!args[0]->IsFunction()) {
70 LOGE("OnKeyEvent args need a function.");
71 return;
72 }
73 RefPtr<JsKeyFunction> JsOnKeyEvent = AceType::MakeRefPtr<JsKeyFunction>(JSRef<JSFunc>::Cast(args[0]));
74 auto onKeyEvent = [execCtx = args.GetExecutionContext(), func = std::move(JsOnKeyEvent)](KeyEventInfo& info) {
75 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
76 ACE_SCORING_EVENT("onKey");
77 func->Execute(info);
78 };
79 ViewAbstractModel::GetInstance()->SetOnKeyEvent(std::move(onKeyEvent));
80 }
81
JsOnHover(const JSCallbackInfo & info)82 void JSInteractableView::JsOnHover(const JSCallbackInfo& info)
83 {
84 LOGD("JSInteractableView JsOnHover");
85 if (info[0]->IsUndefined() && IsDisableEventVersion()) {
86 LOGD("JsOnHover callback is undefined");
87 ViewAbstractModel::GetInstance()->DisableOnHover();
88 return;
89 }
90 if (!info[0]->IsFunction()) {
91 LOGE("the param is not a function");
92 return;
93 }
94 RefPtr<JsHoverFunction> jsOnHoverFunc = AceType::MakeRefPtr<JsHoverFunction>(JSRef<JSFunc>::Cast(info[0]));
95 auto onHover = [execCtx = info.GetExecutionContext(), func = std::move(jsOnHoverFunc)](
96 bool isHover, HoverInfo& hoverInfo) {
97 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
98 ACE_SCORING_EVENT("onHover");
99 func->HoverExecute(isHover, hoverInfo);
100 };
101 ViewAbstractModel::GetInstance()->SetOnHover(std::move(onHover));
102 }
103
JsOnPan(const JSCallbackInfo & args)104 void JSInteractableView::JsOnPan(const JSCallbackInfo& args)
105 {
106 LOGD("JSInteractableView JsOnPan");
107 if (args[0]->IsObject()) {
108 // TODO: JSPanHandler should support ng build
109 #ifndef NG_BUILD
110 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
111 JSPanHandler* handler = obj->Unwrap<JSPanHandler>();
112 if (handler) {
113 handler->CreateComponent(args);
114 }
115 #endif
116 }
117 }
118
JsOnDelete(const JSCallbackInfo & info)119 void JSInteractableView::JsOnDelete(const JSCallbackInfo& info)
120 {
121 LOGD("JSInteractableView JsOnDelete");
122 if (info[0]->IsFunction()) {
123 RefPtr<JsFunction> jsOnDeleteFunc =
124 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
125 auto onDelete = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDeleteFunc)]() {
126 LOGD("onDelete callback");
127 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
128 ACE_SCORING_EVENT("onDelete");
129 func->Execute();
130 };
131 ViewAbstractModel::GetInstance()->SetOnDelete(std::move(onDelete));
132 }
133 }
134
JsTouchable(const JSCallbackInfo & info)135 void JSInteractableView::JsTouchable(const JSCallbackInfo& info)
136 {
137 if (info[0]->IsBoolean()) {
138 ViewAbstractModel::GetInstance()->SetTouchable(info[0]->ToBoolean());
139 }
140 }
141
JsOnClick(const JSCallbackInfo & info)142 void JSInteractableView::JsOnClick(const JSCallbackInfo& info)
143 {
144 LOGD("JSInteractableView JsOnClick");
145 if (info[0]->IsUndefined() && IsDisableEventVersion()) {
146 LOGD("JsOnClick callback is undefined");
147 ViewAbstractModel::GetInstance()->DisableOnClick();
148 return;
149 }
150 if (!info[0]->IsFunction()) {
151 LOGW("the info is not click function");
152 return;
153 }
154 auto jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
155 auto onTap = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc](GestureEvent& info) {
156 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
157 ACE_SCORING_EVENT("onClick");
158 func->Execute(info);
159 };
160
161 auto onClick = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc](const ClickInfo* info) {
162 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
163 ACE_SCORING_EVENT("onClick");
164 func->Execute(*info);
165 };
166
167 ViewAbstractModel::GetInstance()->SetOnClick(std::move(onTap), std::move(onClick));
168 }
169
SetFocusable(bool focusable)170 void JSInteractableView::SetFocusable(bool focusable)
171 {
172 ViewAbstractModel::GetInstance()->SetFocusable(focusable);
173 }
174
SetFocusNode(bool isFocusNode)175 void JSInteractableView::SetFocusNode(bool isFocusNode)
176 {
177 ViewAbstractModel::GetInstance()->SetFocusNode(isFocusNode);
178 }
179
JsOnAppear(const JSCallbackInfo & info)180 void JSInteractableView::JsOnAppear(const JSCallbackInfo& info)
181 {
182 LOGD("JSInteractableView JsOnAppear");
183 if (info[0]->IsUndefined() && IsDisableEventVersion()) {
184 LOGD("JsOnAppear callback is undefined");
185 ViewAbstractModel::GetInstance()->DisableOnAppear();
186 return;
187 }
188 if (info[0]->IsFunction()) {
189 RefPtr<JsFunction> jsOnAppearFunc =
190 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
191 auto onAppear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnAppearFunc)]() {
192 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
193 LOGI("About to call JsOnAppear method on js");
194 ACE_SCORING_EVENT("onAppear");
195 func->Execute();
196 };
197 ViewAbstractModel::GetInstance()->SetOnAppear(std::move(onAppear));
198 }
199 }
200
JsOnDisAppear(const JSCallbackInfo & info)201 void JSInteractableView::JsOnDisAppear(const JSCallbackInfo& info)
202 {
203 LOGD("JSInteractableView JsOnDisAppear");
204 if (info[0]->IsUndefined() && IsDisableEventVersion()) {
205 LOGD("JsOnDisAppear callback is undefined");
206 ViewAbstractModel::GetInstance()->DisableOnDisAppear();
207 return;
208 }
209 if (info[0]->IsFunction()) {
210 RefPtr<JsFunction> jsOnDisAppearFunc =
211 AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
212 auto onDisappear = [execCtx = info.GetExecutionContext(), func = std::move(jsOnDisAppearFunc)]() {
213 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
214 LOGD("Start to call JsOnDisAppear method on js");
215 ACE_SCORING_EVENT("onDisAppear");
216 func->Execute();
217 };
218 ViewAbstractModel::GetInstance()->SetOnDisAppear(std::move(onDisappear));
219 }
220 }
221
JsOnAccessibility(const JSCallbackInfo & info)222 void JSInteractableView::JsOnAccessibility(const JSCallbackInfo& info)
223 {
224 if (!info[0]->IsFunction()) {
225 LOGE("info[0] is not a function.");
226 return;
227 }
228 RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
229 auto onAccessibility = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
230 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
231 ACE_SCORING_EVENT("onAccessibility");
232 func->Execute({ "eventType" }, param);
233 };
234 ViewAbstractModel::GetInstance()->SetOnAccessibility(std::move(onAccessibility));
235 }
236
JsCommonRemoteMessage(const JSCallbackInfo & info)237 void JSInteractableView::JsCommonRemoteMessage(const JSCallbackInfo& info)
238 {
239 if (info.Length() != 0 && info[0]->IsObject()) {
240 RemoteCallback remoteCallback;
241 JsRemoteMessage(info, remoteCallback);
242 ViewAbstractModel::GetInstance()->SetOnRemoteMessage(std::move(remoteCallback));
243 }
244 }
245
JsRemoteMessage(const JSCallbackInfo & info,RemoteCallback & remoteCallback)246 void JSInteractableView::JsRemoteMessage(const JSCallbackInfo& info, RemoteCallback& remoteCallback)
247 {
248 if (info.Length() == 0 || !info[0]->IsObject()) {
249 LOGE("RemoteMessage JSCallbackInfo param is empty or type is not Object.");
250 return;
251 }
252
253 auto eventCallback = GetRemoteMessageEventCallback(info);
254 remoteCallback = [func = std::move(eventCallback)](const BaseEventInfo* info) {
255 auto touchInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
256 if (touchInfo && touchInfo->GetType().compare("onClick") == 0) {
257 func();
258 }
259 };
260 }
261
GetRemoteMessageEventCallback(const JSCallbackInfo & info)262 std::function<void()> JSInteractableView::GetRemoteMessageEventCallback(const JSCallbackInfo& info)
263 {
264 auto obj = JSRef<JSObject>::Cast(info[0]);
265 auto actionValue = obj->GetProperty("action");
266 std::string action;
267 if (actionValue->IsString()) {
268 action = actionValue->ToString();
269 }
270 auto abilityValue = obj->GetProperty("ability");
271 std::string ability;
272 if (abilityValue->IsString()) {
273 ability = abilityValue->ToString();
274 }
275 auto paramsObj = obj->GetProperty("params");
276 std::string params;
277 if (paramsObj->IsObject()) {
278 params = paramsObj->ToString();
279 }
280 auto eventCallback = [action, ability, params]() {
281 LOGE("JSInteractableView::JsRemoteMessage. eventMarker");
282 if (action.compare("message") == 0) {
283 // onCall
284 } else if (action.compare("route") == 0) {
285 // startAbility
286 #ifdef PLUGIN_COMPONENT_SUPPORTED
287 std::vector<std::string> strList;
288 SplitString(ability, '/', strList);
289 if (strList.size() <= 1) {
290 LOGE("App bundleName or abilityName is empty.");
291 return;
292 }
293 int32_t result = PluginManager::GetInstance().StartAbility(strList[0], strList[1], params);
294 if (result != 0) {
295 LOGE("JSInteractableView::JsRemoteMessage: Failed to start the APP %{public}s.", ability.c_str());
296 }
297 #else
298 LOGE("JSInteractableView::JsRemoteMessage: Unsupported Windows and Mac platforms to start APP.");
299 #endif
300 } else {
301 LOGE("action's name is not message or route.");
302 }
303 };
304
305 return eventCallback;
306 }
307
SplitString(const std::string & str,char tag,std::vector<std::string> & strList)308 void JSInteractableView::SplitString(const std::string& str, char tag, std::vector<std::string>& strList)
309 {
310 std::string subStr;
311 for (size_t i = 0; i < str.length(); i++) {
312 if (tag == str[i]) {
313 if (!subStr.empty()) {
314 strList.push_back(subStr);
315 subStr.clear();
316 }
317 } else {
318 subStr.push_back(str[i]);
319 }
320 }
321 if (!subStr.empty()) {
322 strList.push_back(subStr);
323 }
324 }
325 } // namespace OHOS::Ace::Framework
326