• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/log_wrapper.h"
19 #include "core/common/container.h"
20 #ifdef PLUGIN_COMPONENT_SUPPORTED
21 #include "core/common/plugin_manager.h"
22 #endif
23 #include "core/components/gesture_listener/gesture_listener_component.h"
24 #include "core/gestures/click_recognizer.h"
25 #include "core/pipeline/base/single_child.h"
26 #include "frameworks/bridge/declarative_frontend/engine/functions/js_click_function.h"
27 #include "frameworks/bridge/declarative_frontend/engine/functions/js_hover_function.h"
28 #include "frameworks/bridge/declarative_frontend/engine/functions/js_key_function.h"
29 #include "frameworks/bridge/declarative_frontend/engine/js_execution_scope_defines.h"
30 #include "frameworks/bridge/declarative_frontend/jsview/js_pan_handler.h"
31 #include "frameworks/bridge/declarative_frontend/jsview/js_touch_handler.h"
32 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
33 
34 namespace OHOS::Ace::Framework {
35 
JsOnTouch(const JSCallbackInfo & args)36 void JSInteractableView::JsOnTouch(const JSCallbackInfo& args)
37 {
38     LOGD("JSInteractableView JsOnTouch");
39     if (args[0]->IsFunction()) {
40         auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
41         if (!inspector) {
42             LOGE("fail to get inspector for on touch event");
43             return;
44         }
45         auto impl = inspector->GetInspectorFunctionImpl();
46         RefPtr<JsTouchFunction> jsOnTouchFunc = AceType::MakeRefPtr<JsTouchFunction>(JSRef<JSFunc>::Cast(args[0]));
47         auto onTouchId = EventMarker(
48             [execCtx = args.GetExecutionContext(), func = std::move(jsOnTouchFunc), impl](BaseEventInfo* info) {
49                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
50                 if (impl) {
51                     impl->UpdateEventInfo(*info);
52                 }
53                 auto touchInfo = TypeInfoHelper::DynamicCast<TouchEventInfo>(info);
54                 ACE_SCORING_EVENT("onTouch");
55                 func->Execute(*touchInfo);
56             },
57             "onTouch");
58         auto touchComponent = ViewStackProcessor::GetInstance()->GetTouchListenerComponent();
59         touchComponent->SetOnTouchId(onTouchId);
60     }
61 }
62 
JsOnKey(const JSCallbackInfo & args)63 void JSInteractableView::JsOnKey(const JSCallbackInfo& args)
64 {
65     if (args[0]->IsFunction()) {
66         RefPtr<JsKeyFunction> jsOnKeyFunc = AceType::MakeRefPtr<JsKeyFunction>(JSRef<JSFunc>::Cast(args[0]));
67         auto onKeyId = EventMarker(
68             [execCtx = args.GetExecutionContext(), func = std::move(jsOnKeyFunc)](BaseEventInfo* info) {
69                 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
70                 auto keyInfo = TypeInfoHelper::DynamicCast<KeyEventInfo>(info);
71                 ACE_SCORING_EVENT("onKey");
72                 func->Execute(*keyInfo);
73             },
74             "onKey", 0);
75         auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent();
76         focusableComponent->SetFocusable(true);
77         focusableComponent->SetOnKeyId(onKeyId);
78     }
79 }
80 
JsOnHover(const JSCallbackInfo & args)81 void JSInteractableView::JsOnHover(const JSCallbackInfo& args)
82 {
83     if (args[0]->IsFunction()) {
84         RefPtr<JsHoverFunction> jsOnHoverFunc = AceType::MakeRefPtr<JsHoverFunction>(JSRef<JSFunc>::Cast(args[0]));
85         auto onHoverId = [execCtx = args.GetExecutionContext(), func = std::move(jsOnHoverFunc)](bool info) {
86             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
87             ACE_SCORING_EVENT("onHover");
88             func->Execute(info);
89         };
90         auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
91         box->SetOnHoverId(onHoverId);
92     }
93 }
94 
JsOnPan(const JSCallbackInfo & args)95 void JSInteractableView::JsOnPan(const JSCallbackInfo& args)
96 {
97     LOGD("JSInteractableView JsOnPan");
98     if (args[0]->IsObject()) {
99         JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
100         JSPanHandler* handler = obj->Unwrap<JSPanHandler>();
101         if (handler) {
102             handler->CreateComponent(args);
103         }
104     }
105 }
106 
JsOnDelete(const JSCallbackInfo & info)107 void JSInteractableView::JsOnDelete(const JSCallbackInfo& info)
108 {
109     LOGD("JSInteractableView JsOnDelete");
110     if (info[0]->IsFunction()) {
111         RefPtr<JsFunction> jsOnDeleteFunc =
112             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
113         auto onDeleteId = EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsOnDeleteFunc)]() {
114             LOGD("onDelete callback");
115             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
116             ACE_SCORING_EVENT("onDelete");
117             func->Execute();
118         });
119         auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent();
120         focusableComponent->SetOnDeleteId(onDeleteId);
121     }
122 }
123 
JsTouchable(const JSCallbackInfo & info)124 void JSInteractableView::JsTouchable(const JSCallbackInfo& info)
125 {
126     if (info[0]->IsBoolean()) {
127         auto mainComponent = ViewStackProcessor::GetInstance()->GetMainComponent();
128         if (!mainComponent) {
129             return;
130         }
131         mainComponent->SetTouchable(info[0]->ToBoolean());
132     }
133 }
134 
JsOnClick(const JSCallbackInfo & info)135 void JSInteractableView::JsOnClick(const JSCallbackInfo& info)
136 {
137     if (info[0]->IsFunction()) {
138         auto click = ViewStackProcessor::GetInstance()->GetBoxComponent();
139         auto tapGesture = GetTapGesture(info);
140         if (tapGesture) {
141             click->SetOnClick(tapGesture);
142         }
143 
144         auto onClickId = GetClickEventMarker(info);
145         auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent();
146         focusableComponent->SetOnClickId(onClickId);
147     }
148 }
149 
GetClickEventMarker(const JSCallbackInfo & info)150 EventMarker JSInteractableView::GetClickEventMarker(const JSCallbackInfo& info)
151 {
152     auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
153     if (!inspector) {
154         LOGE("fail to get inspector for on get click event marker");
155         return EventMarker();
156     }
157     auto impl = inspector->GetInspectorFunctionImpl();
158     RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
159     auto onClickId = EventMarker(
160         [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), impl](const BaseEventInfo* info) {
161             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
162             auto clickInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
163             auto newInfo = *clickInfo;
164             if (impl) {
165                 impl->UpdateEventInfo(newInfo);
166             }
167             ACE_SCORING_EVENT("onClick");
168             func->Execute(newInfo);
169         });
170     return onClickId;
171 }
172 
GetTapGesture(const JSCallbackInfo & info,int32_t countNum,int32_t fingerNum)173 RefPtr<Gesture> JSInteractableView::GetTapGesture(
174     const JSCallbackInfo& info, int32_t countNum, int32_t fingerNum)
175 {
176     auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
177     if (!inspector) {
178         LOGE("fail to get inspector for on touch event");
179         return nullptr;
180     }
181     auto impl = inspector->GetInspectorFunctionImpl();
182     RefPtr<Gesture> tapGesture = AceType::MakeRefPtr<TapGesture>(countNum, fingerNum);
183     RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
184     tapGesture->SetOnActionId(
185         [execCtx = info.GetExecutionContext(), func = std::move(jsOnClickFunc), impl](GestureEvent& info) {
186             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
187             if (impl) {
188                 impl->UpdateEventInfo(info);
189             }
190             ACE_SCORING_EVENT("onClick");
191             func->Execute(info);
192         });
193     return tapGesture;
194 }
195 
GetRemoteMessageTapGesture(const JSCallbackInfo & info)196 RefPtr<Gesture> JSInteractableView::GetRemoteMessageTapGesture(const JSCallbackInfo& info)
197 {
198     RefPtr<Gesture> tapGesture = AceType::MakeRefPtr<TapGesture>();
199     RefPtr<JsClickFunction> jsOnClickFunc = AceType::MakeRefPtr<JsClickFunction>(JSRef<JSFunc>::Cast(info[0]));
200     auto eventCallback = GetRemoteMessageEventCallback(info);
201     tapGesture->SetOnActionId([func = std::move(eventCallback)]
202         (const GestureEvent& info) {
203         func();
204     });
205     return tapGesture;
206 }
207 
SetFocusable(bool focusable)208 void JSInteractableView::SetFocusable(bool focusable)
209 {
210     auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent();
211     if (focusableComponent) {
212         focusableComponent->SetFocusable(focusable);
213     }
214 }
SetFocusNode(bool isFocusNode)215 void JSInteractableView::SetFocusNode(bool isFocusNode)
216 {
217     auto focusableComponent = ViewStackProcessor::GetInstance()->GetFocusableComponent(false);
218     if (focusableComponent) {
219         focusableComponent->SetFocusNode(!isFocusNode);
220     }
221 }
222 
JsOnAppear(const JSCallbackInfo & info)223 void JSInteractableView::JsOnAppear(const JSCallbackInfo& info)
224 {
225     if (info[0]->IsFunction()) {
226         RefPtr<JsFunction> jsOnAppearFunc =
227             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
228 
229         auto onAppearId = EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsOnAppearFunc)]() {
230             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
231             LOGI("About to call JsOnAppear method on js");
232             ACE_SCORING_EVENT("onAppear");
233             func->Execute();
234         });
235         auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
236         component->SetOnAppearEventId(onAppearId);
237     }
238 }
239 
JsOnDisAppear(const JSCallbackInfo & info)240 void JSInteractableView::JsOnDisAppear(const JSCallbackInfo& info)
241 {
242     if (info[0]->IsFunction()) {
243         RefPtr<JsFunction> jsOnDisAppearFunc =
244             AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
245         auto onDisAppearId = EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsOnDisAppearFunc)]() {
246             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
247             LOGD("Start to call JsOnDisAppear method on js");
248             ACE_SCORING_EVENT("onDisAppear");
249             func->Execute();
250         });
251         auto component = ViewStackProcessor::GetInstance()->GetMainComponent();
252         component->SetOnDisappearEventId(onDisAppearId);
253     }
254 }
255 
JsOnAccessibility(const JSCallbackInfo & info)256 void JSInteractableView::JsOnAccessibility(const JSCallbackInfo& info)
257 {
258     auto inspector = ViewStackProcessor::GetInstance()->GetInspectorComposedComponent();
259     if (!inspector) {
260         LOGE("this component does not hava inspetor");
261         return;
262     }
263     inspector->SetAccessibilityEvent(GetEventMarker(info, { "eventType" }));
264 }
265 
UpdateEventTarget(NodeId id,BaseEventInfo & info)266 void JSInteractableView::UpdateEventTarget(NodeId id, BaseEventInfo& info)
267 {
268     auto container = Container::Current();
269     if (!container) {
270         LOGE("fail to get container");
271         return;
272     }
273     auto context = container->GetPipelineContext();
274     if (!context) {
275         LOGE("fail to get context");
276         return;
277     }
278     auto accessibilityManager = context->GetAccessibilityManager();
279     if (!accessibilityManager) {
280         LOGE("fail to get accessibility manager");
281         return;
282     }
283     accessibilityManager->UpdateEventTarget(id, info);
284 }
285 
GetEventMarker(const JSCallbackInfo & info,const std::vector<std::string> & keys)286 EventMarker JSInteractableView::GetEventMarker(const JSCallbackInfo& info, const std::vector<std::string>& keys)
287 {
288     if (!info[0]->IsFunction()) {
289         LOGE("info[0] is not a function.");
290         return EventMarker();
291     }
292 
293     RefPtr<JsFunction> jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
294     auto eventMarker =
295         EventMarker([execCtx = info.GetExecutionContext(), func = std::move(jsFunc), keys](const std::string& param) {
296             JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
297             ACE_SCORING_EVENT("onClick");
298             func->Execute(keys, param);
299         });
300     return eventMarker;
301 }
302 
JsCommonRemoteMessage(const JSCallbackInfo & info)303 void JSInteractableView::JsCommonRemoteMessage(const JSCallbackInfo& info)
304 {
305     if (info.Length() != 0 && info[0]->IsObject()) {
306         auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
307         EventMarker remoteMessageEventId;
308         JsRemoteMessage(info, remoteMessageEventId);
309         box->SetRemoteMessageEvent(remoteMessageEventId);
310     }
311 }
312 
JsRemoteMessage(const JSCallbackInfo & info,EventMarker & eventMarker)313 void JSInteractableView::JsRemoteMessage(const JSCallbackInfo& info, EventMarker& eventMarker)
314 {
315     if (info.Length() == 0 || !info[0]->IsObject()) {
316         LOGE("RemoteMessage JSCallbackInfo param is empty or type is not Object.");
317         return;
318     }
319 
320     auto eventCallback = GetRemoteMessageEventCallback(info);
321     eventMarker = EventMarker(
322         [func = std::move(eventCallback)](BaseEventInfo* info) {
323             auto touchInfo = TypeInfoHelper::DynamicCast<ClickInfo>(info);
324             if (touchInfo && touchInfo->GetType().compare("onClick") == 0) {
325                 func();
326             }
327         });
328 }
329 
GetRemoteMessageEventCallback(const JSCallbackInfo & info)330 std::function<void()> JSInteractableView::GetRemoteMessageEventCallback(const JSCallbackInfo& info)
331 {
332     auto obj = JSRef<JSObject>::Cast(info[0]);
333     auto actionValue = obj->GetProperty("action");
334     std::string action;
335     if (actionValue->IsString()) {
336         action = actionValue->ToString();
337     }
338     auto abilityValue = obj->GetProperty("ability");
339     std::string ability;
340     if (abilityValue->IsString()) {
341         ability = abilityValue->ToString();
342     }
343     auto paramsObj = obj->GetProperty("params");
344     std::string params;
345     if (paramsObj->IsObject()) {
346         params = paramsObj->ToString();
347     }
348     auto eventCallback = [action, ability, params]() {
349         LOGE("JSInteractableView::JsRemoteMessage. eventMarker");
350         if (action.compare("message") == 0) {
351             // onCall
352         } else if (action.compare("route") == 0) {
353             // startAbility
354 #ifdef PLUGIN_COMPONENT_SUPPORTED
355             std::vector<std::string> strList;
356             SplitString(ability, '/', strList);
357             if (strList.size() <= 1) {
358                 LOGE("App bundleName or abilityName is empty.");
359                 return;
360             }
361             int32_t result = PluginManager::GetInstance().StartAbility(strList[0], strList[1], params);
362             if (result != 0) {
363                 LOGE("JSInteractableView::JsRemoteMessage: Failed to start the APP %{public}s.", ability.c_str());
364             }
365 #else
366             LOGE("JSInteractableView::JsRemoteMessage: Unsupport Windows and Mac platforms to start APP.");
367 #endif
368         } else {
369             LOGE("action's name is not message or route.");
370         }
371     };
372 
373     return eventCallback;
374 }
375 
SplitString(const std::string & str,char tag,std::vector<std::string> & strList)376 void JSInteractableView::SplitString(const std::string& str, char tag, std::vector<std::string>& strList)
377 {
378     std::string subStr;
379     for (size_t i = 0; i < str.length(); i++) {
380         if (tag == str[i]) {
381             if (!subStr.empty()) {
382                 strList.push_back(subStr);
383                 subStr.clear();
384             }
385         } else {
386             subStr.push_back(str[i]);
387         }
388     }
389     if (!subStr.empty()) {
390         strList.push_back(subStr);
391     }
392 }
393 } // namespace OHOS::Ace::Framework
394