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