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