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
117 std::string backgroundUri;
118 if (backgroundUriArg->IsString(vm)) {
119 backgroundUri = backgroundUriArg->ToString(vm)->ToString(vm);
120 }
121
122 std::string foregroundUri;
123 if (foregroundUriArg->IsString(vm)) {
124 foregroundUri = foregroundUriArg->ToString(vm)->ToString(vm);
125 }
126
127 std::string secondaryUri;
128 if (secondaryUriArg->IsString(vm)) {
129 secondaryUri = secondaryUriArg->ToString(vm)->ToString(vm);
130 }
131
132 if (secondaryUri.empty() && !backgroundUri.empty()) {
133 secondaryUri = backgroundUri;
134 }
135
136 GetArkUINodeModifiers()->getRatingModifier()->setStarStyle(
137 nativeNode, backgroundUri.c_str(), foregroundUri.c_str(), secondaryUri.c_str());
138 return panda::JSValueRef::Undefined(vm);
139 }
140
ResetStarStyle(ArkUIRuntimeCallInfo * runtimeCallInfo)141 ArkUINativeModuleValue RatingBridge::ResetStarStyle(ArkUIRuntimeCallInfo* runtimeCallInfo)
142 {
143 EcmaVM* vm = runtimeCallInfo->GetVM();
144 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
145 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
146 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
147 GetArkUINodeModifiers()->getRatingModifier()->resetStarStyle(nativeNode);
148 return panda::JSValueRef::Undefined(vm);
149 }
150
SetContentModifierBuilder(ArkUIRuntimeCallInfo * runtimeCallInfo)151 ArkUINativeModuleValue RatingBridge::SetContentModifierBuilder(ArkUIRuntimeCallInfo* runtimeCallInfo)
152 {
153 EcmaVM* vm = runtimeCallInfo->GetVM();
154 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
155 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
156 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
157 auto* frameNode = reinterpret_cast<FrameNode*>(firstArg->ToNativePointer(vm)->Value());
158 if (!secondArg->IsObject(vm)) {
159 RatingModelNG::SetBuilderFunc(frameNode, nullptr);
160 return panda::JSValueRef::Undefined(vm);
161 }
162 panda::CopyableGlobal<panda::ObjectRef> obj(vm, secondArg);
163 auto containerId = Container::CurrentId();
164 RatingModelNG::SetBuilderFunc(frameNode,
165 [vm, frameNode, obj = std::move(obj), containerId](
166 RatingConfiguration config) -> RefPtr<FrameNode> {
167 ContainerScope scope(containerId);
168 auto context = ArkTSUtils::GetContext(vm);
169 CHECK_EQUAL_RETURN(context->IsUndefined(), true, nullptr);
170 const char* keys[] = { "stars", "indicator", "rating", "stepSize", "enabled", "triggerChange" };
171 Local<JSValueRef> values[] = { panda::NumberRef::New(vm, config.starNum_),
172 panda::BooleanRef::New(vm, config.isIndicator_),
173 panda::NumberRef::New(vm, config.rating_),
174 panda::NumberRef::New(vm, config.stepSize_),
175 panda::BooleanRef::New(vm, config.enabled_),
176 panda::FunctionRef::New(vm, JsRatingChangeCallback) };
177 auto rating = panda::ObjectRef::NewWithNamedProperties(vm, ArraySize(keys), keys, values);
178 rating->SetNativePointerFieldCount(vm, 1);
179 rating->SetNativePointerField(vm, 0, static_cast<void*>(frameNode));
180 panda::Local<panda::JSValueRef> params[NUM_2] = { context, rating };
181 LocalScope pandaScope(vm);
182 panda::TryCatch trycatch(vm);
183 auto makeFunc = obj.ToLocal()->Get(vm, panda::StringRef::NewFromUtf8(vm, "makeContentModifierNode"));
184 CHECK_EQUAL_RETURN(makeFunc->IsFunction(vm), false, nullptr);
185 panda::Local<panda::FunctionRef> func = makeFunc;
186 auto result = func->Call(vm, obj.ToLocal(), params, 2);
187 JSNApi::ExecutePendingJob(vm);
188 CHECK_EQUAL_RETURN(result.IsEmpty() || trycatch.HasCaught() || !result->IsObject(vm), true, nullptr);
189 panda::Local<panda::JSValueRef> nodeptr =
190 result->ToObject(vm)->Get(vm, panda::StringRef::NewFromUtf8(vm, NODEPTR_OF_UINODE));
191 CHECK_EQUAL_RETURN(nodeptr.IsEmpty() || nodeptr->IsUndefined() || nodeptr->IsNull(), true, nullptr);
192 auto* frameNode = reinterpret_cast<FrameNode*>(nodeptr->ToNativePointer(vm)->Value());
193 CHECK_NULL_RETURN(frameNode, nullptr);
194 return AceType::Claim(frameNode);
195 });
196 return panda::JSValueRef::Undefined(vm);
197 }
198
SetRatingOptions(ArkUIRuntimeCallInfo * runtimeCallInfo)199 ArkUINativeModuleValue RatingBridge::SetRatingOptions(ArkUIRuntimeCallInfo* runtimeCallInfo)
200 {
201 EcmaVM* vm = runtimeCallInfo->GetVM();
202 CHECK_NULL_RETURN(vm, panda::JSValueRef::Undefined(vm));
203 CHECK_EQUAL_RETURN(runtimeCallInfo->GetArgsNumber() != NUM_3, true, panda::JSValueRef::Undefined(vm));
204 Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(NUM_0);
205 Local<JSValueRef> ratingArg = runtimeCallInfo->GetCallArgRef(NUM_1);
206 Local<JSValueRef> indicatorArg = runtimeCallInfo->GetCallArgRef(NUM_2);
207 auto pointer = nodeArg->ToNativePointer(vm);
208 CHECK_EQUAL_RETURN(pointer.IsEmpty(), true, panda::JSValueRef::Undefined(vm));
209 auto nativeNode = nodePtr(pointer->Value());
210 CHECK_NULL_RETURN(nativeNode, panda::JSValueRef::Undefined(vm));
211
212 double rating = 0.0;
213 if (!ratingArg->IsNull() && ratingArg->IsNumber()) {
214 rating = ratingArg->ToNumber(vm)->Value();
215 }
216 if (LessNotEqual(rating, 0.0)) {
217 rating = 0.0;
218 }
219
220 int32_t indicator = 0;
221 if (!indicatorArg->IsNull() && indicatorArg->IsBoolean()) {
222 indicator = indicatorArg->ToBoolean(vm)->Value();
223 }
224 GetArkUINodeModifiers()->getRatingModifier()->setRatingOptions(
225 nativeNode, rating, indicator);
226 return panda::JSValueRef::Undefined(vm);
227 }
228
SetOnChange(ArkUIRuntimeCallInfo * runtimeCallInfo)229 ArkUINativeModuleValue RatingBridge::SetOnChange(ArkUIRuntimeCallInfo* runtimeCallInfo)
230 {
231 EcmaVM* vm = runtimeCallInfo->GetVM();
232 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
233 int32_t argsNumber = runtimeCallInfo->GetArgsNumber();
234 if (argsNumber != NUM_2) {
235 return panda::JSValueRef::Undefined(vm);
236 }
237 Local<JSValueRef> nativeNodeArg = runtimeCallInfo->GetCallArgRef(NUM_0);
238 Local<JSValueRef> callbackArg = runtimeCallInfo->GetCallArgRef(NUM_1);
239 auto nativeNode = nodePtr(nativeNodeArg->ToNativePointer(vm)->Value());
240 auto frameNode = reinterpret_cast<FrameNode*>(nativeNode);
241 CHECK_NULL_RETURN(frameNode, panda::NativePointerRef::New(vm, nullptr));
242 if (callbackArg->IsUndefined() || callbackArg->IsNull() || !callbackArg->IsFunction(vm)) {
243 GetArkUINodeModifiers()->getRatingModifier()->resetOnChange(nativeNode);
244 return panda::JSValueRef::Undefined(vm);
245 }
246 panda::Local<panda::FunctionRef> func = callbackArg->ToObject(vm);
247 std::function<void(const std::string&)> callback = [vm, frameNode, func = panda::CopyableGlobal(vm, func)](
248 const std::string& star) {
249 panda::LocalScope pandaScope(vm);
250 panda::TryCatch trycatch(vm);
251 PipelineContext::SetCallBackNode(AceType::WeakClaim(frameNode));
252 panda::Local<panda::NumberRef> starParam = panda::NumberRef::New(vm, std::stod(star));
253 panda::Local<panda::JSValueRef> params[PARAM_ARR_LENGTH_1] = { starParam };
254 func->Call(vm, func.ToLocal(), params, PARAM_ARR_LENGTH_1);
255 };
256 GetArkUINodeModifiers()->getRatingModifier()->setOnChange(nativeNode, reinterpret_cast<void*>(&callback));
257 return panda::JSValueRef::Undefined(vm);
258 }
259
ResetOnChange(ArkUIRuntimeCallInfo * runtimeCallInfo)260 ArkUINativeModuleValue RatingBridge::ResetOnChange(ArkUIRuntimeCallInfo* runtimeCallInfo)
261 {
262 EcmaVM* vm = runtimeCallInfo->GetVM();
263 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
264 Local<JSValueRef> nativeNodeArg = runtimeCallInfo->GetCallArgRef(NUM_0);
265 auto nativeNode = nodePtr(nativeNodeArg->ToNativePointer(vm)->Value());
266 GetArkUINodeModifiers()->getRatingModifier()->resetOnChange(nativeNode);
267 return panda::JSValueRef::Undefined(vm);
268 }
269
270 } // namespace OHOS::Ace::NG