• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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