1 /*
2 * Copyright (c) 2021-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
16 #include "bridge/declarative_frontend/jsview/js_badge.h"
17
18 #include "base/geometry/dimension.h"
19 #include "base/log/ace_trace.h"
20 #include "base/utils/utils.h"
21 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_theme.h"
22 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_theme_utils.h"
23 #include "core/components/common/layout/grid_container_info.h"
24 #include "core/components_ng/pattern/badge/badge_model_ng.h"
25 #include "frameworks/bridge/declarative_frontend/jsview/models/badge_model_impl.h"
26
27 namespace OHOS::Ace {
28 std::unique_ptr<BadgeModel> BadgeModel::instance_ = nullptr;
29 std::mutex BadgeModel::mutex_;
30
GetInstance()31 BadgeModel* BadgeModel::GetInstance()
32 {
33 if (!instance_) {
34 std::lock_guard<std::mutex> lock(mutex_);
35 if (!instance_) {
36 #ifdef NG_BUILD
37 instance_.reset(new NG::BadgeModelNG());
38 #else
39 if (Container::IsCurrentUseNewPipeline()) {
40 instance_.reset(new NG::BadgeModelNG());
41 } else {
42 instance_.reset(new Framework::BadgeModelImpl());
43 }
44 #endif
45 }
46 }
47 return instance_.get();
48 }
49 } // namespace OHOS::Ace
50
51 namespace OHOS::Ace::Framework {
Create(const JSCallbackInfo & info)52 void JSBadge::Create(const JSCallbackInfo& info)
53 {
54 if (!info[0]->IsObject()) {
55 return;
56 }
57
58 auto frameNode = BadgeModel::GetInstance()->CreateBadgeFrameNode();
59 BadgeParameters badgeParameters = CreateBadgeParameters(info);
60 BadgeModel::GetInstance()->CreateByFrameNode(frameNode, badgeParameters);
61 }
62
CreateBadgeParameters(const JSCallbackInfo & info)63 BadgeParameters JSBadge::CreateBadgeParameters(const JSCallbackInfo& info)
64 {
65 BadgeParameters badgeParameters;
66 if (!info[0]->IsObject()) {
67 return badgeParameters;
68 }
69
70 auto themeColors = JSThemeUtils::GetThemeColors();
71
72 auto badgeTheme = GetTheme<BadgeTheme>();
73 CHECK_NULL_RETURN(badgeTheme, BadgeParameters());
74 auto obj = JSRef<JSObject>::Cast(info[0]);
75 auto value = obj->GetProperty("value");
76 if (!value->IsNull() && value->IsString()) {
77 auto label = value->ToString();
78 badgeParameters.badgeValue = label;
79 } else if (!value->IsNull() && value->IsObject()) {
80 std::string valueResult;
81 if (SystemProperties::ConfigChangePerform()) {
82 RefPtr<ResourceObject> resObj;
83 ParseJsString(value, valueResult, resObj);
84 badgeParameters.resourceBadgeValueObject = resObj;
85 badgeParameters.badgeValue = valueResult;
86 } else {
87 ParseJsString(value, valueResult);
88 badgeParameters.badgeValue = valueResult;
89 }
90 }
91
92 auto position = obj->GetProperty("position");
93 if (!position->IsNull() && position->IsNumber()) {
94 badgeParameters.isPositionXy = false;
95 badgeParameters.badgePosition = position->ToNumber<int32_t>();
96 } else if (!position->IsNull() && position->IsObject()) {
97 badgeParameters.isPositionXy = true;
98 auto postionValue = JSRef<JSObject>::Cast(position);
99 JSRef<JSVal> xVal = postionValue->GetProperty("x");
100 JSRef<JSVal> yVal = postionValue->GetProperty("y");
101 CalcDimension dimenX;
102 CalcDimension dimenY;
103 RefPtr<ResourceObject> resObjX;
104 RefPtr<ResourceObject> resObjY;
105 if (SystemProperties::ConfigChangePerform()) {
106 bool xState = ParseJsDimensionVp(xVal, dimenX, resObjX);
107 bool yState = ParseJsDimensionVp(yVal, dimenY, resObjY);
108 badgeParameters.resourceBadgePositionXObject = resObjX;
109 badgeParameters.resourceBadgePositionYObject = resObjY;
110 badgeParameters.badgePositionXByUser = true;
111 badgeParameters.badgePositionYByUser = true;
112 bool hasX = resObjX || xState;
113 bool hasY = resObjY || yState;
114 if (!(hasX || hasY)) {
115 badgeParameters.badgePositionX = badgeTheme->GetBadgePositionX();
116 badgeParameters.badgePositionY = badgeTheme->GetBadgePositionY();
117 badgeParameters.resourceBadgePositionXObject = nullptr;
118 badgeParameters.resourceBadgePositionYObject = nullptr;
119 badgeParameters.badgePositionXByUser = false;
120 badgeParameters.badgePositionYByUser = false;
121 } else {
122 badgeParameters.badgePositionX = dimenX;
123 badgeParameters.badgePositionY = dimenY;
124 }
125 } else {
126 bool xResult = ParseJsDimensionVp(xVal, dimenX);
127 bool yResult = ParseJsDimensionVp(yVal, dimenY);
128 if (!(xResult || yResult)) {
129 badgeParameters.badgePositionX = badgeTheme->GetBadgePositionX();
130 badgeParameters.badgePositionY = badgeTheme->GetBadgePositionY();
131 } else {
132 badgeParameters.badgePositionX = dimenX;
133 badgeParameters.badgePositionY = dimenY;
134 }
135 }
136 }
137
138 auto style = obj->GetProperty("style");
139 if (!style->IsNull() && style->IsObject()) {
140 auto value = JSRef<JSObject>::Cast(style);
141 JSRef<JSVal> colorValue = value->GetProperty("color");
142 JSRef<JSVal> fontSizeValue = value->GetProperty("fontSize");
143 JSRef<JSVal> badgeSizeValue = value->GetProperty("badgeSize");
144 JSRef<JSVal> badgeColorValue = value->GetProperty("badgeColor");
145 JSRef<JSVal> borderColorValue = value->GetProperty("borderColor");
146 JSRef<JSVal> borderWidthValue = value->GetProperty("borderWidth");
147 JSRef<JSVal> fontWeightValue = value->GetProperty("fontWeight");
148
149 bool isDefaultFontSize = true;
150 bool isDefaultBadgeSize = true;
151
152 Color colorVal;
153 if (SystemProperties::ConfigChangePerform()) {
154 RefPtr<ResourceObject> resObj;
155 badgeParameters.badgeTextColorByUser = true;
156 bool state = ParseJsColor(colorValue, colorVal, resObj);
157 badgeParameters.resourceColorObject = resObj;
158 if (state) {
159 badgeParameters.badgeTextColor = colorVal;
160 } else if (themeColors) {
161 badgeParameters.badgeTextColor = themeColors->FontOnPrimary();
162 badgeParameters.badgeTextColorByUser = false;
163 } else {
164 badgeParameters.badgeTextColorByUser = false;
165 }
166 } else {
167 if (ParseJsColor(colorValue, colorVal)) {
168 badgeParameters.badgeTextColor = colorVal;
169 } else if (themeColors) {
170 badgeParameters.badgeTextColor = themeColors->FontOnPrimary();
171 }
172 }
173
174 CalcDimension fontSize;
175 if (SystemProperties::ConfigChangePerform()) {
176 RefPtr<ResourceObject> resObj;
177 badgeParameters.badgeFontSizeByUser = true;
178 bool state = ParseJsDimensionNG(fontSizeValue, fontSize, DimensionUnit::FP, resObj);
179 badgeParameters.resourceFontSizeObject = resObj;
180 if (state && fontSize.IsNonNegative() && fontSize.Unit() != DimensionUnit::PERCENT) {
181 badgeParameters.badgeFontSize = fontSize;
182 isDefaultFontSize = false;
183 } else {
184 badgeParameters.badgeFontSizeByUser = false;
185 badgeParameters.badgeFontSize =
186 !fontSizeValue->IsUndefined() ? badgeTheme->GetBadgeFontSize() : UNDEFINED_DIMENSION;
187 }
188 } else {
189 if (ParseJsDimensionNG(fontSizeValue, fontSize, DimensionUnit::FP) && fontSize.IsNonNegative() &&
190 fontSize.Unit() != DimensionUnit::PERCENT) {
191 badgeParameters.badgeFontSize = fontSize;
192 isDefaultFontSize = false;
193 } else if (!fontSizeValue->IsUndefined()) {
194 badgeParameters.badgeFontSize = badgeTheme->GetBadgeFontSize();
195 } else {
196 badgeParameters.badgeFontSize = UNDEFINED_DIMENSION;
197 }
198 }
199
200 CalcDimension badgeSize;
201 if (SystemProperties::ConfigChangePerform()) {
202 RefPtr<ResourceObject> resObj;
203 badgeParameters.badgeCircleSizeByUser = true;
204 bool state = ParseJsDimensionNG(badgeSizeValue, badgeSize, DimensionUnit::FP, resObj);
205 badgeParameters.resourceBadgeSizeObject = resObj;
206 if (state && badgeSize.IsNonNegative() && badgeSize.Unit() != DimensionUnit::PERCENT) {
207 badgeParameters.badgeCircleSize = badgeSize;
208 isDefaultBadgeSize = false;
209 } else {
210 badgeParameters.badgeCircleSize = badgeTheme->GetBadgeCircleSize();
211 badgeParameters.badgeCircleSizeByUser = false;
212 }
213 } else {
214 if (ParseJsDimensionNG(badgeSizeValue, badgeSize, DimensionUnit::FP) && badgeSize.IsNonNegative() &&
215 badgeSize.Unit() != DimensionUnit::PERCENT) {
216 badgeParameters.badgeCircleSize = badgeSize;
217 isDefaultBadgeSize = false;
218 } else {
219 badgeParameters.badgeCircleSize = badgeTheme->GetBadgeCircleSize();
220 }
221 }
222
223 BadgeModel::GetInstance()->SetIsDefault(isDefaultFontSize, isDefaultBadgeSize);
224 Color color;
225 if (SystemProperties::ConfigChangePerform()) {
226 RefPtr<ResourceObject> badgeColorResObj;
227 badgeParameters.badgeColorByUser = false;
228 bool state = ParseJsColor(badgeColorValue, color, badgeColorResObj);
229 badgeParameters.resourceBadgeColorObject = badgeColorResObj;
230 if (state) {
231 badgeParameters.badgeColor = color;
232 badgeParameters.badgeColorByUser = true;
233 } else if (themeColors) {
234 badgeParameters.badgeColor = themeColors->Warning();
235 }
236 } else {
237 if (ParseJsColor(badgeColorValue, color)) {
238 badgeParameters.badgeColor = color;
239 } else if (themeColors) {
240 badgeParameters.badgeColor = themeColors->Warning();
241 }
242 }
243 CalcDimension borderWidth;
244
245 if (SystemProperties::ConfigChangePerform()) {
246 RefPtr<ResourceObject> resObj;
247 badgeParameters.badgeBorderWidthByUser = true;
248 bool state = ParseJsDimensionVp(borderWidthValue, borderWidth, resObj);
249 badgeParameters.resourceBorderWidthObject = resObj;
250 if (state && borderWidth.IsNonNegative() && borderWidth.Unit() != DimensionUnit::PERCENT) {
251 badgeParameters.badgeBorderWidth = borderWidth;
252 } else {
253 badgeParameters.badgeBorderWidth = badgeTheme->GetBadgeBorderWidth();
254 badgeParameters.badgeBorderWidthByUser = false;
255 }
256 } else {
257 if (ParseJsDimensionVp(borderWidthValue, borderWidth) && borderWidth.IsNonNegative() &&
258 borderWidth.Unit() != DimensionUnit::PERCENT) {
259 badgeParameters.badgeBorderWidth = borderWidth;
260 } else {
261 badgeParameters.badgeBorderWidth = badgeTheme->GetBadgeBorderWidth();
262 }
263 }
264 Color borderColor;
265 if (SystemProperties::ConfigChangePerform()) {
266 RefPtr<ResourceObject> borderColorResObj;
267 badgeParameters.badgeBorderColorByUser = false;
268 bool state = ParseJsColor(borderColorValue, borderColor, borderColorResObj);
269 badgeParameters.resourceBorderColorObject = borderColorResObj;
270 if (state) {
271 badgeParameters.badgeBorderColor = borderColor;
272 badgeParameters.badgeBorderColorByUser = true;
273 } else {
274 badgeParameters.badgeBorderColor =
275 themeColors ? themeColors->Warning() : badgeTheme->GetBadgeBorderColor();
276 }
277 } else {
278 if (ParseJsColor(borderColorValue, borderColor)) {
279 badgeParameters.badgeBorderColor = borderColor;
280 } else {
281 badgeParameters.badgeBorderColor =
282 themeColors ? themeColors->Warning() : badgeTheme->GetBadgeBorderColor();
283 }
284 }
285
286 std::string fontWeight;
287 if (fontWeightValue->IsNumber()) {
288 fontWeight = std::to_string(fontWeightValue->ToNumber<int32_t>());
289 badgeParameters.badgeFontWeight = ConvertStrToFontWeight(fontWeight);
290 } else if (SystemProperties::ConfigChangePerform()) {
291 RefPtr<ResourceObject> resObj;
292 ParseJsString(fontWeightValue, fontWeight, resObj);
293 badgeParameters.resourceFontWeightObject = resObj;
294 badgeParameters.badgeFontWeight = ConvertStrToFontWeight(fontWeight);
295 } else {
296 if (!ParseJsString(fontWeightValue, fontWeight)) {
297 badgeParameters.badgeFontWeight = FontWeight::NORMAL;
298 }
299 badgeParameters.badgeFontWeight = ConvertStrToFontWeight(fontWeight);
300 }
301 }
302
303 auto count = obj->GetProperty("count");
304 if (!count->IsNull() && count->IsNumber()) {
305 badgeParameters.badgeCount = count->ToNumber<int32_t>();
306 }
307 auto maxCount = obj->GetProperty("maxCount");
308 if (!maxCount->IsNull() && maxCount->IsNumber()) {
309 badgeParameters.badgeMaxCount = maxCount->ToNumber<int32_t>();
310 } else {
311 badgeParameters.badgeMaxCount = badgeTheme->GetMaxCount();
312 }
313
314 return badgeParameters;
315 }
316
JSBind(BindingTarget globalObj)317 void JSBadge::JSBind(BindingTarget globalObj)
318 {
319 JSClass<JSBadge>::Declare("Badge");
320
321 MethodOptions opt = MethodOptions::NONE;
322 JSClass<JSBadge>::StaticMethod("create", &JSBadge::Create, opt);
323 JSClass<JSBadge>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
324 JSClass<JSBadge>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
325 JSClass<JSBadge>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
326 JSClass<JSBadge>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
327 JSClass<JSBadge>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
328
329 JSClass<JSBadge>::InheritAndBind<JSContainerBase>(globalObj);
330 }
331 } // namespace OHOS::Ace::Framework
332