1 /*
2 * Copyright (c) 2023 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 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_rating_bridge.h"
16 #include "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
17 #include "core/components_ng/base/frame_node.h"
18 #include "core/components_ng/pattern/rating/rating_model_ng.h"
19
20 namespace OHOS::Ace::NG {
21 constexpr double STEPS_DEFAULT = 0.5;
22 constexpr double STEPS_MIN_SIZE = 0.1;
23 constexpr int32_t STARS_DEFAULT = 5;
24 constexpr int NUM_0 = 0;
25 constexpr int NUM_1 = 1;
26 constexpr int NUM_2 = 2;
27 constexpr int NUM_3 = 3;
28 constexpr int PARAM_ARR_LENGTH_1 = 1;
29 const char* NODEPTR_OF_UINODE = "nodePtr_";
JsRatingChangeCallback(panda::JsiRuntimeCallInfo * runtimeCallInfo)30 panda::Local<panda::JSValueRef> JsRatingChangeCallback(panda::JsiRuntimeCallInfo* runtimeCallInfo)
31 {
32 auto vm = runtimeCallInfo->GetVM();
33 int32_t argc = static_cast<int32_t>(runtimeCallInfo->GetArgsNumber());
34 if (argc != 1) {
35 return panda::JSValueRef::Undefined(vm);
36 }
37 auto firstArg = runtimeCallInfo->GetCallArgRef(0);
38 if (!firstArg->IsNumber()) {
39 return panda::JSValueRef::Undefined(vm);
40 }
41 double value = firstArg->ToNumber(vm)->Value();
42 auto ref = runtimeCallInfo->GetThisRef();
43 auto obj = ref->ToObject(vm);
44 if (obj->GetNativePointerFieldCount(vm) < 1) {
45 return panda::JSValueRef::Undefined(vm);
46 }
47 auto frameNode = static_cast<FrameNode*>(obj->GetNativePointerField(vm, 0));
48 CHECK_NULL_RETURN(frameNode, panda::JSValueRef::Undefined(vm));
49 RatingModelNG::SetChangeValue(frameNode, value);
50 return panda::JSValueRef::Undefined(vm);
51 }
52
SetStars(ArkUIRuntimeCallInfo * runtimeCallInfo)53 ArkUINativeModuleValue RatingBridge::SetStars(ArkUIRuntimeCallInfo* runtimeCallInfo)
54 {
55 EcmaVM* vm = runtimeCallInfo->GetVM();
56 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
57 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
58 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
59 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
60 int32_t stars = secondArg->Int32Value(vm);
61 if (stars <= 0) {
62 stars = STARS_DEFAULT;
63 }
64 GetArkUINodeModifiers()->getRatingModifier()->setStars(nativeNode, stars);
65 return panda::JSValueRef::Undefined(vm);
66 }
67
ResetStars(ArkUIRuntimeCallInfo * runtimeCallInfo)68 ArkUINativeModuleValue RatingBridge::ResetStars(ArkUIRuntimeCallInfo* runtimeCallInfo)
69 {
70 EcmaVM* vm = runtimeCallInfo->GetVM();
71 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
72 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
73 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
74 GetArkUINodeModifiers()->getRatingModifier()->resetStars(nativeNode);
75 return panda::JSValueRef::Undefined(vm);
76 }
SetRatingStepSize(ArkUIRuntimeCallInfo * runtimeCallInfo)77 ArkUINativeModuleValue RatingBridge::SetRatingStepSize(ArkUIRuntimeCallInfo* runtimeCallInfo)
78 {
79 EcmaVM* vm = runtimeCallInfo->GetVM();
80 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
81 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
82 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
83 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
84
85 if (secondArg->IsNull() || !secondArg->IsNumber()) {
86 GetArkUINodeModifiers()->getRatingModifier()->resetRatingStepSize(nativeNode);
87 return panda::JSValueRef::Undefined(vm);
88 }
89 auto steps = secondArg->ToNumber(vm)->Value();
90 if (LessNotEqual(steps, STEPS_MIN_SIZE)) {
91 steps = STEPS_DEFAULT;
92 }
93 GetArkUINodeModifiers()->getRatingModifier()->setRatingStepSize(nativeNode, steps);
94 return panda::JSValueRef::Undefined(vm);
95 }
96
ResetRatingStepSize(ArkUIRuntimeCallInfo * runtimeCallInfo)97 ArkUINativeModuleValue RatingBridge::ResetRatingStepSize(ArkUIRuntimeCallInfo* runtimeCallInfo)
98 {
99 EcmaVM* vm = runtimeCallInfo->GetVM();
100 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
101 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
102 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
103 GetArkUINodeModifiers()->getRatingModifier()->resetRatingStepSize(nativeNode);
104 return panda::JSValueRef::Undefined(vm);
105 }
106
SetStarStyle(ArkUIRuntimeCallInfo * runtimeCallInfo)107 ArkUINativeModuleValue RatingBridge::SetStarStyle(ArkUIRuntimeCallInfo* runtimeCallInfo)
108 {
109 EcmaVM* vm = runtimeCallInfo->GetVM();
110 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
111 Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(NUM_0);
112 Local<JSValueRef> backgroundUriArg = runtimeCallInfo->GetCallArgRef(NUM_1);
113 Local<JSValueRef> foregroundUriArg = runtimeCallInfo->GetCallArgRef(NUM_2);
114 Local<JSValueRef> secondaryUriArg = runtimeCallInfo->GetCallArgRef(NUM_3);
115 auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
116 ArkUIRatingStyleStruct resObj;
117 std::string backgroundUri;
118 RefPtr<ResourceObject> backgroundResObj;
119 if (!ArkTSUtils::ParseJsMedia(vm, backgroundUriArg, backgroundUri, backgroundResObj)) {
120 ArkTSUtils::ParseJsString(vm, backgroundUriArg, backgroundUri, backgroundResObj);
121 }
122 resObj.backgroundResObj = AceType::RawPtr(backgroundResObj);
123
124 std::string foregroundUri;
125 RefPtr<ResourceObject> foregroundResObj;
126 if (!ArkTSUtils::ParseJsMedia(vm, foregroundUriArg, foregroundUri, foregroundResObj)) {
127 ArkTSUtils::ParseJsString(vm, foregroundUriArg, foregroundUri, foregroundResObj);
128 }
129 resObj.foregroundResObj = AceType::RawPtr(foregroundResObj);
130
131 std::string secondaryUri;
132 RefPtr<ResourceObject> secondaryResObj;
133 if (!ArkTSUtils::ParseJsMedia(vm, secondaryUriArg, secondaryUri, secondaryResObj)) {
134 ArkTSUtils::ParseJsString(vm, secondaryUriArg, secondaryUri, secondaryResObj);
135 }
136 resObj.secondaryResObj = AceType::RawPtr(secondaryResObj);
137
138 if (secondaryUri.empty() && !backgroundUri.empty()) {
139 secondaryUri = backgroundUri;
140 resObj.secondaryResObj = AceType::RawPtr(backgroundResObj);
141 }
142
143 GetArkUINodeModifiers()->getRatingModifier()->setStarStylePtr(
144 nativeNode, backgroundUri.c_str(), foregroundUri.c_str(), secondaryUri.c_str(), resObj);
145 return panda::JSValueRef::Undefined(vm);
146 }
147
ResetStarStyle(ArkUIRuntimeCallInfo * runtimeCallInfo)148 ArkUINativeModuleValue RatingBridge::ResetStarStyle(ArkUIRuntimeCallInfo* runtimeCallInfo)
149 {
150 EcmaVM* vm = runtimeCallInfo->GetVM();
151 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
152 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
153 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
154 GetArkUINodeModifiers()->getRatingModifier()->resetStarStyle(nativeNode);
155 return panda::JSValueRef::Undefined(vm);
156 }
157
SetContentModifierBuilder(ArkUIRuntimeCallInfo * runtimeCallInfo)158 ArkUINativeModuleValue RatingBridge::SetContentModifierBuilder(ArkUIRuntimeCallInfo* runtimeCallInfo)
159 {
160 EcmaVM* vm = runtimeCallInfo->GetVM();
161 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
162 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
163 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
164 auto* frameNode = reinterpret_cast<FrameNode*>(firstArg->ToNativePointer(vm)->Value());
165 if (!secondArg->IsObject(vm)) {
166 RatingModelNG::SetBuilderFunc(frameNode, nullptr);
167 return panda::JSValueRef::Undefined(vm);
168 }
169 panda::CopyableGlobal<panda::ObjectRef> obj(vm, secondArg);
170 auto containerId = Container::CurrentId();
171 RatingModelNG::SetBuilderFunc(frameNode,
172 [vm, frameNode, obj = std::move(obj), containerId](
173 RatingConfiguration config) -> RefPtr<FrameNode> {
174 ContainerScope scope(containerId);
175 auto context = ArkTSUtils::GetContext(vm);
176 CHECK_EQUAL_RETURN(context->IsUndefined(), true, nullptr);
177 const char* keys[] = { "stars", "indicator", "rating", "stepSize", "enabled", "triggerChange" };
178 Local<JSValueRef> values[] = { panda::NumberRef::New(vm, config.starNum_),
179 panda::BooleanRef::New(vm, config.isIndicator_),
180 panda::NumberRef::New(vm, config.rating_),
181 panda::NumberRef::New(vm, config.stepSize_),
182 panda::BooleanRef::New(vm, config.enabled_),
183 panda::FunctionRef::New(vm, JsRatingChangeCallback) };
184 auto rating = panda::ObjectRef::NewWithNamedProperties(vm, ArraySize(keys), keys, values);
185 rating->SetNativePointerFieldCount(vm, 1);
186 rating->SetNativePointerField(vm, 0, static_cast<void*>(frameNode));
187 panda::Local<panda::JSValueRef> params[NUM_2] = { context, rating };
188 LocalScope pandaScope(vm);
189 panda::TryCatch trycatch(vm);
190 auto makeFunc = obj.ToLocal()->Get(vm, panda::StringRef::NewFromUtf8(vm, "makeContentModifierNode"));
191 CHECK_EQUAL_RETURN(makeFunc->IsFunction(vm), false, nullptr);
192 panda::Local<panda::FunctionRef> func = makeFunc;
193 auto result = func->Call(vm, obj.ToLocal(), params, 2);
194 JSNApi::ExecutePendingJob(vm);
195 CHECK_EQUAL_RETURN(result.IsEmpty() || trycatch.HasCaught() || !result->IsObject(vm), true, nullptr);
196 panda::Local<panda::JSValueRef> nodeptr =
197 result->ToObject(vm)->Get(vm, panda::StringRef::NewFromUtf8(vm, NODEPTR_OF_UINODE));
198 CHECK_EQUAL_RETURN(nodeptr.IsEmpty() || nodeptr->IsUndefined() || nodeptr->IsNull(), true, nullptr);
199 auto* frameNode = reinterpret_cast<FrameNode*>(nodeptr->ToNativePointer(vm)->Value());
200 CHECK_NULL_RETURN(frameNode, nullptr);
201 return AceType::Claim(frameNode);
202 });
203 return panda::JSValueRef::Undefined(vm);
204 }
205
SetRatingOptions(ArkUIRuntimeCallInfo * runtimeCallInfo)206 ArkUINativeModuleValue RatingBridge::SetRatingOptions(ArkUIRuntimeCallInfo* runtimeCallInfo)
207 {
208 EcmaVM* vm = runtimeCallInfo->GetVM();
209 CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm));
210 CHECK_EQUAL_RETURN(runtimeCallInfo->GetArgsNumber() != NUM_3, true, panda::JSValueRef::Undefined(vm));
211 Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(NUM_0);
212 Local<JSValueRef> ratingArg = runtimeCallInfo->GetCallArgRef(NUM_1);
213 Local<JSValueRef> indicatorArg = runtimeCallInfo->GetCallArgRef(NUM_2);
214 auto pointer = nodeArg->ToNativePointer(vm);
215 CHECK_EQUAL_RETURN(pointer.IsEmpty(), true, panda::JSValueRef::Undefined(vm));
216 auto nativeNode = nodePtr(pointer->Value());
217 CHECK_NULL_RETURN(nativeNode, panda::JSValueRef::Undefined(vm));
218
219 double rating = 0.0;
220 if (!ratingArg->IsNull() && ratingArg->IsNumber()) {
221 rating = ratingArg->ToNumber(vm)->Value();
222 }
223 if (LessNotEqual(rating, 0.0)) {
224 rating = 0.0;
225 }
226
227 int32_t indicator = 0;
228 if (!indicatorArg->IsNull() && indicatorArg->IsBoolean()) {
229 indicator = indicatorArg->ToBoolean(vm)->Value();
230 }
231 GetArkUINodeModifiers()->getRatingModifier()->setRatingOptions(
232 nativeNode, rating, indicator);
233 return panda::JSValueRef::Undefined(vm);
234 }
235
SetOnChange(ArkUIRuntimeCallInfo * runtimeCallInfo)236 ArkUINativeModuleValue RatingBridge::SetOnChange(ArkUIRuntimeCallInfo* runtimeCallInfo)
237 {
238 EcmaVM* vm = runtimeCallInfo->GetVM();
239 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
240 uint32_t argsNumber = runtimeCallInfo->GetArgsNumber();
241 if (argsNumber != NUM_2) {
242 return panda::JSValueRef::Undefined(vm);
243 }
244 Local<JSValueRef> nativeNodeArg = runtimeCallInfo->GetCallArgRef(NUM_0);
245 Local<JSValueRef> callbackArg = runtimeCallInfo->GetCallArgRef(NUM_1);
246 auto nativeNode = nodePtr(nativeNodeArg->ToNativePointer(vm)->Value());
247 auto frameNode = reinterpret_cast<FrameNode*>(nativeNode);
248 CHECK_NULL_RETURN(frameNode, panda::NativePointerRef::New(vm, nullptr));
249 if (callbackArg->IsUndefined() || callbackArg->IsNull() || !callbackArg->IsFunction(vm)) {
250 GetArkUINodeModifiers()->getRatingModifier()->resetOnChange(nativeNode);
251 return panda::JSValueRef::Undefined(vm);
252 }
253 panda::Local<panda::FunctionRef> func = callbackArg->ToObject(vm);
254 std::function<void(const std::string&)> callback = [vm, frameNode, func = panda::CopyableGlobal(vm, func)](
255 const std::string& star) {
256 panda::LocalScope pandaScope(vm);
257 panda::TryCatch trycatch(vm);
258 PipelineContext::SetCallBackNode(AceType::WeakClaim(frameNode));
259 panda::Local<panda::NumberRef> starParam = panda::NumberRef::New(vm, StringUtils::StringToDouble(star));
260 panda::Local<panda::JSValueRef> params[PARAM_ARR_LENGTH_1] = { starParam };
261 func->Call(vm, func.ToLocal(), params, PARAM_ARR_LENGTH_1);
262 };
263 GetArkUINodeModifiers()->getRatingModifier()->setOnChange(nativeNode, reinterpret_cast<void*>(&callback));
264 return panda::JSValueRef::Undefined(vm);
265 }
266
ResetOnChange(ArkUIRuntimeCallInfo * runtimeCallInfo)267 ArkUINativeModuleValue RatingBridge::ResetOnChange(ArkUIRuntimeCallInfo* runtimeCallInfo)
268 {
269 EcmaVM* vm = runtimeCallInfo->GetVM();
270 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
271 Local<JSValueRef> nativeNodeArg = runtimeCallInfo->GetCallArgRef(NUM_0);
272 auto nativeNode = nodePtr(nativeNodeArg->ToNativePointer(vm)->Value());
273 GetArkUINodeModifiers()->getRatingModifier()->resetOnChange(nativeNode);
274 return panda::JSValueRef::Undefined(vm);
275 }
276
277 } // namespace OHOS::Ace::NG