• 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/js_frontend/engine/jsi/jsi_component_api_bridge.h"
17 
18 #include "core/animation/curves.h"
19 #include "frameworks/bridge/common/dom/dom_list.h"
20 #include "frameworks/bridge/common/utils/utils.h"
21 
22 namespace OHOS::Ace::Framework {
23 
JsGetScrollOffset(const shared_ptr<JsRuntime> & runtime,NodeId nodeId)24 shared_ptr<JsValue> JsiComponentApiBridge::JsGetScrollOffset(const shared_ptr<JsRuntime>& runtime, NodeId nodeId)
25 {
26     if (!runtime) {
27         LOGE("JsGetScrollOffset failed. runtime is null.");
28         return nullptr;
29     }
30     auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
31     if (!engine) {
32         LOGE("JsGetScrollOffset failed. engine is null.");
33         return runtime->NewUndefined();
34     }
35     auto page = engine->GetRunningPage();
36     if (!page) {
37         LOGE("JsGetScrollOffset failed. page is null.");
38         return runtime->NewUndefined();
39     }
40     Offset offset;
41     auto task = [nodeId, page, &offset]() {
42         auto domDoc = page->GetDomDocument();
43         if (!domDoc) {
44             return;
45         }
46         auto domNode = domDoc->GetDOMNodeById(nodeId);
47         if (!domNode) {
48             return;
49         }
50         auto domList = AceType::DynamicCast<DOMList>(domNode);
51         if (domList) {
52             offset = domList->GetCurrentOffset();
53             return;
54         }
55 
56         auto scrollComponent = domNode->GetScrollComponent();
57         if (!scrollComponent) {
58             return;
59         }
60         auto controller = scrollComponent->GetScrollPositionController();
61         if (!controller) {
62             return;
63         }
64         offset = controller->GetCurrentOffset();
65     };
66     auto delegate = engine->GetFrontendDelegate();
67     if (!delegate) {
68         LOGE("JsGetScrollOffset failed. delegate is null.");
69         return runtime->NewUndefined();
70     }
71     delegate->PostSyncTaskToPage(task);
72     shared_ptr<JsValue> offsetContext = runtime->NewObject();
73     offsetContext->SetProperty(runtime, "x", runtime->NewNumber(offset.GetX()));
74     offsetContext->SetProperty(runtime, "y", runtime->NewNumber(offset.GetY()));
75     return offsetContext;
76 }
77 
JsGetBoundingRect(const shared_ptr<JsRuntime> & runtime,NodeId nodeId)78 shared_ptr<JsValue> JsiComponentApiBridge::JsGetBoundingRect(const shared_ptr<JsRuntime>& runtime, NodeId nodeId)
79 {
80     if (!runtime) {
81         LOGE("JsGetBoundingRect failed. runtime is null.");
82         return nullptr;
83     }
84     auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
85     if (!engine) {
86         LOGE("JsGetBoundingRect failed. engine is null.");
87         return runtime->NewUndefined();
88     }
89     auto delegate = engine->GetFrontendDelegate();
90     if (!delegate) {
91         LOGE("JsGetBoundingRect failed. delegate is null.");
92         return runtime->NewUndefined();
93     }
94     Rect boundingRect = delegate->GetBoundingRectData(nodeId);
95     shared_ptr<JsValue> rectContext = runtime->NewObject();
96     rectContext->SetProperty(runtime, "width", runtime->NewNumber(boundingRect.Width()));
97     rectContext->SetProperty(runtime, "height", runtime->NewNumber(boundingRect.Height()));
98     rectContext->SetProperty(runtime, "top", runtime->NewNumber(boundingRect.Top()));
99     rectContext->SetProperty(runtime, "left", runtime->NewNumber(boundingRect.Left()));
100     return rectContext;
101 }
102 
JsGetInspector(const shared_ptr<JsRuntime> & runtime,NodeId nodeId)103 shared_ptr<JsValue> JsiComponentApiBridge::JsGetInspector(const shared_ptr<JsRuntime>& runtime, NodeId nodeId)
104 {
105     if (!runtime) {
106         LOGE("JsGetInspector failed. runtime is null.");
107         return nullptr;
108     }
109     auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
110     if (!engine) {
111         LOGE("JsGetInspector failed. engine is null.");
112         return runtime->NewUndefined();
113     }
114     auto delegate = engine->GetFrontendDelegate();
115     if (!delegate) {
116         LOGE("JsGetInspector failed. delegate is null.");
117         return runtime->NewUndefined();
118     }
119     auto attributes = delegate->GetInspector(nodeId);
120     shared_ptr<JsValue> result = runtime->NewString(attributes);
121     return result;
122 }
123 
JsScrollTo(const shared_ptr<JsRuntime> & runtime,const std::string & arguments,NodeId nodeId)124 void JsiComponentApiBridge::JsScrollTo(
125     const shared_ptr<JsRuntime>& runtime, const std::string& arguments, NodeId nodeId)
126 {
127     if (!runtime) {
128         LOGE("JsScrollTo failed. runtime is null.");
129         return;
130     }
131     auto engine = static_cast<JsiEngineInstance*>(runtime->GetEmbedderData());
132     if (!engine) {
133         LOGE("JsScrollTo failed. engine is null.");
134         return;
135     }
136     auto page = engine->GetRunningPage();
137     if (!page) {
138         LOGE("JsScrollTo failed. page is null.");
139         return;
140     }
141     auto task = [nodeId, page, arguments]() {
142         auto domDoc = page->GetDomDocument();
143         if (!domDoc) {
144             LOGE("JsScrollTo failed. dom document is null!");
145             return;
146         }
147         auto domNode = domDoc->GetDOMNodeById(nodeId);
148         if (!domNode) {
149             LOGE("JsScrollTo failed. dom node is null!");
150             return;
151         }
152         std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(arguments);
153         if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() < 1) {
154             LOGE("JsScrollTo failed. parse args error");
155             return;
156         }
157         std::unique_ptr<JsonValue> scrollToPara = argsValue->GetArrayItem(0);
158         int32_t index = scrollToPara->GetInt("index", 0);
159         auto domList = AceType::DynamicCast<DOMList>(domNode);
160         if (domList) {
161             // list has specialized scrollTo method.
162             domList->ScrollToMethod(index);
163             return;
164         }
165 
166         auto scrollComponent = domNode->GetScrollComponent();
167         if (!scrollComponent) {
168             return;
169         }
170         auto controller = scrollComponent->GetScrollPositionController();
171         if (!controller) {
172             return;
173         }
174 
175         std::string id = scrollToPara->GetString("id", "");
176         double position = scrollToPara->GetDouble("position", 0.0);
177         double duration = scrollToPara->GetDouble("duration", 300.0); // Default duration is 300ms.
178         std::string timingFunction = scrollToPara->GetString("timingFunction", "ease");
179         std::string successId = scrollToPara->GetString("success", "");
180         std::string failId = scrollToPara->GetString("fail", "");
181         std::string completeId = scrollToPara->GetString("complete", "");
182         auto context = domNode->GetPipelineContext();
183         auto callback = [context, successId, completeId]() {
184             auto refContext = context.Upgrade();
185             if (refContext) {
186                 refContext->SendCallbackMessageToFrontend(successId, std::string("\"success\",null"));
187                 refContext->SendCallbackMessageToFrontend(completeId, std::string("\"complete\",null"));
188             }
189         };
190 
191         bool result = false;
192         if (scrollToPara->Contains("position")) {
193             result = controller->AnimateTo(position, duration, CreateCurve(timingFunction), false, callback);
194         } else if (scrollToPara->Contains("id") && !id.empty()) {
195             result = controller->AnimateToTarget(id, duration, CreateCurve(timingFunction), false, callback);
196         } else {
197             LOGW("JsScrollTo failed. param not valid.");
198         }
199         if (!result) {
200             auto refContext = context.Upgrade();
201             if (refContext) {
202                 refContext->SendCallbackMessageToFrontend(failId, std::string("\"fail\",null"));
203                 refContext->SendCallbackMessageToFrontend(completeId, std::string("\"complete\",null"));
204             }
205         }
206     };
207 
208     auto delegate = engine->GetFrontendDelegate();
209     if (!delegate) {
210         LOGE("JsScrollTo failed. delegate is null.");
211         return;
212     }
213     delegate->PostSyncTaskToPage(task);
214 }
215 
216 } // namespace OHOS::Ace::Framework