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 const char* NODEPTR_OF_UINODE = "nodePtr_";
JsRatingChangeCallback(panda::JsiRuntimeCallInfo * runtimeCallInfo)29 panda::Local<panda::JSValueRef> JsRatingChangeCallback(panda::JsiRuntimeCallInfo* runtimeCallInfo)
30 {
31 auto vm = runtimeCallInfo->GetVM();
32 int32_t argc = static_cast<int32_t>(runtimeCallInfo->GetArgsNumber());
33 if (argc != 1) {
34 return panda::JSValueRef::Undefined(vm);
35 }
36 auto firstArg = runtimeCallInfo->GetCallArgRef(0);
37 if (!firstArg->IsNumber()) {
38 return panda::JSValueRef::Undefined(vm);
39 }
40 double value = firstArg->ToNumber(vm)->Value();
41 auto ref = runtimeCallInfo->GetThisRef();
42 auto obj = ref->ToObject(vm);
43 if (obj->GetNativePointerFieldCount(vm) < 1) {
44 return panda::JSValueRef::Undefined(vm);
45 }
46 auto frameNode = static_cast<FrameNode*>(obj->GetNativePointerField(vm, 0));
47 CHECK_NULL_RETURN(frameNode, panda::JSValueRef::Undefined(vm));
48 RatingModelNG::SetChangeValue(frameNode, value);
49 return panda::JSValueRef::Undefined(vm);
50 }
51
SetStars(ArkUIRuntimeCallInfo * runtimeCallInfo)52 ArkUINativeModuleValue RatingBridge::SetStars(ArkUIRuntimeCallInfo* runtimeCallInfo)
53 {
54 EcmaVM* vm = runtimeCallInfo->GetVM();
55 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
56 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
57 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
58 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
59 int32_t stars = secondArg->Int32Value(vm);
60 if (stars <= 0) {
61 stars = STARS_DEFAULT;
62 }
63 GetArkUINodeModifiers()->getRatingModifier()->setStars(nativeNode, stars);
64 return panda::JSValueRef::Undefined(vm);
65 }
66
ResetStars(ArkUIRuntimeCallInfo * runtimeCallInfo)67 ArkUINativeModuleValue RatingBridge::ResetStars(ArkUIRuntimeCallInfo* runtimeCallInfo)
68 {
69 EcmaVM* vm = runtimeCallInfo->GetVM();
70 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
71 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
72 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
73 GetArkUINodeModifiers()->getRatingModifier()->resetStars(nativeNode);
74 return panda::JSValueRef::Undefined(vm);
75 }
SetRatingStepSize(ArkUIRuntimeCallInfo * runtimeCallInfo)76 ArkUINativeModuleValue RatingBridge::SetRatingStepSize(ArkUIRuntimeCallInfo* runtimeCallInfo)
77 {
78 EcmaVM* vm = runtimeCallInfo->GetVM();
79 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
80 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
81 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
82 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
83
84 if (secondArg->IsNull() || !secondArg->IsNumber()) {
85 GetArkUINodeModifiers()->getRatingModifier()->resetRatingStepSize(nativeNode);
86 return panda::JSValueRef::Undefined(vm);
87 }
88 auto steps = secondArg->ToNumber(vm)->Value();
89 if (LessNotEqual(steps, STEPS_MIN_SIZE)) {
90 steps = STEPS_DEFAULT;
91 }
92 GetArkUINodeModifiers()->getRatingModifier()->setRatingStepSize(nativeNode, steps);
93 return panda::JSValueRef::Undefined(vm);
94 }
95
ResetRatingStepSize(ArkUIRuntimeCallInfo * runtimeCallInfo)96 ArkUINativeModuleValue RatingBridge::ResetRatingStepSize(ArkUIRuntimeCallInfo* runtimeCallInfo)
97 {
98 EcmaVM* vm = runtimeCallInfo->GetVM();
99 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
100 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
101 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
102 GetArkUINodeModifiers()->getRatingModifier()->resetRatingStepSize(nativeNode);
103 return panda::JSValueRef::Undefined(vm);
104 }
105
SetStarStyle(ArkUIRuntimeCallInfo * runtimeCallInfo)106 ArkUINativeModuleValue RatingBridge::SetStarStyle(ArkUIRuntimeCallInfo* runtimeCallInfo)
107 {
108 EcmaVM* vm = runtimeCallInfo->GetVM();
109 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
110 Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(NUM_0);
111 Local<JSValueRef> backgroundUriArg = runtimeCallInfo->GetCallArgRef(NUM_1);
112 Local<JSValueRef> foregroundUriArg = runtimeCallInfo->GetCallArgRef(NUM_2);
113 Local<JSValueRef> secondaryUriArg = runtimeCallInfo->GetCallArgRef(NUM_3);
114 auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
115
116 std::string backgroundUri;
117 if (backgroundUriArg->IsString(vm)) {
118 backgroundUri = backgroundUriArg->ToString(vm)->ToString(vm);
119 }
120
121 std::string foregroundUri;
122 if (foregroundUriArg->IsString(vm)) {
123 foregroundUri = foregroundUriArg->ToString(vm)->ToString(vm);
124 }
125
126 std::string secondaryUri;
127 if (secondaryUriArg->IsString(vm)) {
128 secondaryUri = secondaryUriArg->ToString(vm)->ToString(vm);
129 }
130
131 if (secondaryUri.empty() && !backgroundUri.empty()) {
132 secondaryUri = backgroundUri;
133 }
134
135 GetArkUINodeModifiers()->getRatingModifier()->setStarStyle(
136 nativeNode, backgroundUri.c_str(), foregroundUri.c_str(), secondaryUri.c_str());
137 return panda::JSValueRef::Undefined(vm);
138 }
139
ResetStarStyle(ArkUIRuntimeCallInfo * runtimeCallInfo)140 ArkUINativeModuleValue RatingBridge::ResetStarStyle(ArkUIRuntimeCallInfo* runtimeCallInfo)
141 {
142 EcmaVM* vm = runtimeCallInfo->GetVM();
143 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
144 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
145 auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value());
146 GetArkUINodeModifiers()->getRatingModifier()->resetStarStyle(nativeNode);
147 return panda::JSValueRef::Undefined(vm);
148 }
149
SetContentModifierBuilder(ArkUIRuntimeCallInfo * runtimeCallInfo)150 ArkUINativeModuleValue RatingBridge::SetContentModifierBuilder(ArkUIRuntimeCallInfo* runtimeCallInfo)
151 {
152 EcmaVM* vm = runtimeCallInfo->GetVM();
153 CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr));
154 Local<JSValueRef> firstArg = runtimeCallInfo->GetCallArgRef(NUM_0);
155 Local<JSValueRef> secondArg = runtimeCallInfo->GetCallArgRef(NUM_1);
156 auto* frameNode = reinterpret_cast<FrameNode*>(firstArg->ToNativePointer(vm)->Value());
157 if (!secondArg->IsObject(vm)) {
158 RatingModelNG::SetBuilderFunc(frameNode, nullptr);
159 return panda::JSValueRef::Undefined(vm);
160 }
161 panda::CopyableGlobal<panda::ObjectRef> obj(vm, secondArg);
162 auto containerId = Container::CurrentId();
163 RatingModelNG::SetBuilderFunc(frameNode,
164 [vm, frameNode, obj = std::move(obj), containerId](
165 RatingConfiguration config) -> RefPtr<FrameNode> {
166 ContainerScope scope(containerId);
167 auto context = ArkTSUtils::GetContext(vm);
168 CHECK_EQUAL_RETURN(context->IsUndefined(), true, nullptr);
169 const char* keys[] = { "stars", "indicator", "rating", "stepSize", "enabled", "triggerChange" };
170 Local<JSValueRef> values[] = { panda::NumberRef::New(vm, config.starNum_),
171 panda::BooleanRef::New(vm, config.isIndicator_),
172 panda::NumberRef::New(vm, config.rating_),
173 panda::NumberRef::New(vm, config.stepSize_),
174 panda::BooleanRef::New(vm, config.enabled_),
175 panda::FunctionRef::New(vm, JsRatingChangeCallback) };
176 auto rating = panda::ObjectRef::NewWithNamedProperties(vm, ArraySize(keys), keys, values);
177 rating->SetNativePointerFieldCount(vm, 1);
178 rating->SetNativePointerField(vm, 0, static_cast<void*>(frameNode));
179 panda::Local<panda::JSValueRef> params[NUM_2] = { context, rating };
180 LocalScope pandaScope(vm);
181 panda::TryCatch trycatch(vm);
182 auto makeFunc = obj.ToLocal()->Get(vm, panda::StringRef::NewFromUtf8(vm, "makeContentModifierNode"));
183 CHECK_EQUAL_RETURN(makeFunc->IsFunction(vm), false, nullptr);
184 panda::Local<panda::FunctionRef> func = makeFunc;
185 auto result = func->Call(vm, obj.ToLocal(), params, 2);
186 JSNApi::ExecutePendingJob(vm);
187 CHECK_EQUAL_RETURN(result.IsEmpty() || trycatch.HasCaught() || !result->IsObject(vm), true, nullptr);
188 panda::Local<panda::JSValueRef> nodeptr =
189 result->ToObject(vm)->Get(vm, panda::StringRef::NewFromUtf8(vm, NODEPTR_OF_UINODE));
190 CHECK_EQUAL_RETURN(nodeptr.IsEmpty() || nodeptr->IsUndefined() || nodeptr->IsNull(), true, nullptr);
191 auto* frameNode = reinterpret_cast<FrameNode*>(nodeptr->ToNativePointer(vm)->Value());
192 CHECK_NULL_RETURN(frameNode, nullptr);
193 return AceType::Claim(frameNode);
194 });
195 return panda::JSValueRef::Undefined(vm);
196 }
197 } // namespace OHOS::Ace::NG