* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bridge/declarative_frontend/jsview/js_badge.h"
#include "base/geometry/dimension.h"
#include "base/log/ace_trace.h"
#include "base/utils/utils.h"
#include "bridge/declarative_frontend/ark_theme/theme_apply/js_theme.h"
#include "bridge/declarative_frontend/ark_theme/theme_apply/js_theme_utils.h"
#include "core/common/dynamic_module_helper.h"
#include "core/components/badge/badge_theme.h"
#include "core/components/common/layout/grid_container_info.h"
#include "core/components_ng/pattern/badge/badge_model.h"
#include "core/components_ng/pattern/badge/badge_model_ng.h"
namespace OHOS::Ace {
std::unique_ptr<BadgeModel> BadgeModel::instance_ = nullptr;
std::mutex BadgeModel::mutex_;
BadgeModel* BadgeModel::GetInstance()
{
if (!instance_) {
std::lock_guard<std::mutex> lock(mutex_);
if (!instance_) {
#ifdef NG_BUILD
instance_.reset(new NG::BadgeModelNG());
#else
if (Container::IsCurrentUseNewPipeline()) {
instance_.reset(new NG::BadgeModelNG());
} else {
static auto loader = DynamicModuleHelper::GetInstance().GetLoaderByName("badge");
static BadgeModel* instance = loader ? reinterpret_cast<BadgeModel*>(loader->CreateModel()) : nullptr;
return instance;
}
#endif
}
}
return instance_.get();
}
}
namespace OHOS::Ace::Framework {
void JSBadge::Create(const JSCallbackInfo& info)
{
if (!info[0]->IsObject()) {
return;
}
auto frameNode = BadgeModel::GetInstance()->CreateBadgeFrameNode();
BadgeParameters badgeParameters = CreateBadgeParameters(info);
BadgeModel::GetInstance()->CreateByFrameNode(frameNode, badgeParameters);
}
BadgeParameters JSBadge::CreateBadgeParameters(const JSCallbackInfo& info)
{
BadgeParameters badgeParameters;
if (!info[0]->IsObject()) {
return badgeParameters;
}
auto themeColors = JSThemeUtils::GetThemeColors();
auto badgeTheme = GetTheme<BadgeTheme>();
CHECK_NULL_RETURN(badgeTheme, BadgeParameters());
auto obj = JSRef<JSObject>::Cast(info[0]);
auto value = obj->GetProperty("value");
if (!value->IsNull() && value->IsString()) {
auto label = value->ToString();
badgeParameters.badgeValue = label;
} else if (!value->IsNull() && value->IsObject()) {
std::string valueResult;
if (SystemProperties::ConfigChangePerform()) {
RefPtr<ResourceObject> resObj;
ParseJsString(value, valueResult, resObj);
badgeParameters.resourceBadgeValueObject = resObj;
badgeParameters.badgeValue = valueResult;
} else {
ParseJsString(value, valueResult);
badgeParameters.badgeValue = valueResult;
}
}
auto position = obj->GetProperty("position");
if (!position->IsNull() && position->IsNumber()) {
badgeParameters.isPositionXy = false;
badgeParameters.badgePosition = position->ToNumber<int32_t>();
} else if (!position->IsNull() && position->IsObject()) {
badgeParameters.isPositionXy = true;
auto postionValue = JSRef<JSObject>::Cast(position);
JSRef<JSVal> xVal = postionValue->GetProperty("x");
JSRef<JSVal> yVal = postionValue->GetProperty("y");
CalcDimension dimenX;
CalcDimension dimenY;
RefPtr<ResourceObject> resObjX;
RefPtr<ResourceObject> resObjY;
if (SystemProperties::ConfigChangePerform()) {
bool xState = ParseJsDimensionVp(xVal, dimenX, resObjX);
bool yState = ParseJsDimensionVp(yVal, dimenY, resObjY);
badgeParameters.resourceBadgePositionXObject = resObjX;
badgeParameters.resourceBadgePositionYObject = resObjY;
badgeParameters.badgePositionXByUser = true;
badgeParameters.badgePositionYByUser = true;
bool hasX = resObjX || xState;
bool hasY = resObjY || yState;
if (!(hasX || hasY)) {
badgeParameters.badgePositionX = badgeTheme->GetBadgePositionX();
badgeParameters.badgePositionY = badgeTheme->GetBadgePositionY();
badgeParameters.resourceBadgePositionXObject = nullptr;
badgeParameters.resourceBadgePositionYObject = nullptr;
badgeParameters.badgePositionXByUser = false;
badgeParameters.badgePositionYByUser = false;
} else {
badgeParameters.badgePositionX = dimenX;
badgeParameters.badgePositionY = dimenY;
}
} else {
bool xResult = ParseJsDimensionVp(xVal, dimenX);
bool yResult = ParseJsDimensionVp(yVal, dimenY);
if (!(xResult || yResult)) {
badgeParameters.badgePositionX = badgeTheme->GetBadgePositionX();
badgeParameters.badgePositionY = badgeTheme->GetBadgePositionY();
} else {
badgeParameters.badgePositionX = dimenX;
badgeParameters.badgePositionY = dimenY;
}
}
}
auto style = obj->GetProperty("style");
if (!style->IsNull() && style->IsObject()) {
auto value = JSRef<JSObject>::Cast(style);
JSRef<JSVal> colorValue = value->GetProperty("color");
JSRef<JSVal> fontSizeValue = value->GetProperty("fontSize");
JSRef<JSVal> badgeSizeValue = value->GetProperty("badgeSize");
JSRef<JSVal> badgeColorValue = value->GetProperty("badgeColor");
JSRef<JSVal> borderColorValue = value->GetProperty("borderColor");
JSRef<JSVal> borderWidthValue = value->GetProperty("borderWidth");
JSRef<JSVal> fontWeightValue = value->GetProperty("fontWeight");
JSRef<JSVal> outerBorderColorValue = value->GetProperty("outerBorderColor");
JSRef<JSVal> outerBorderWidthValue = value->GetProperty("outerBorderWidth");
JSRef<JSVal> enableAutoAvoidanceValue = value->GetProperty("enableAutoAvoidance");
bool isDefaultFontSize = true;
bool isDefaultBadgeSize = true;
Color colorVal;
if (SystemProperties::ConfigChangePerform()) {
RefPtr<ResourceObject> resObj;
badgeParameters.badgeTextColorByUser = true;
bool state = ParseJsColor(colorValue, colorVal, resObj);
badgeParameters.resourceColorObject = resObj;
if (state) {
badgeParameters.badgeTextColor = colorVal;
} else if (themeColors) {
badgeParameters.badgeTextColor = themeColors->FontOnPrimary();
badgeParameters.badgeTextColorByUser = false;
} else {
badgeParameters.badgeTextColorByUser = false;
}
} else {
if (ParseJsColor(colorValue, colorVal)) {
badgeParameters.badgeTextColor = colorVal;
} else if (themeColors) {
badgeParameters.badgeTextColor = themeColors->FontOnPrimary();
}
}
CalcDimension fontSize;
if (SystemProperties::ConfigChangePerform()) {
RefPtr<ResourceObject> resObj;
badgeParameters.badgeFontSizeByUser = true;
bool state = ParseJsDimensionNG(fontSizeValue, fontSize, DimensionUnit::FP, resObj);
badgeParameters.resourceFontSizeObject = resObj;
if (state && fontSize.IsNonNegative() && fontSize.Unit() != DimensionUnit::PERCENT) {
badgeParameters.badgeFontSize = fontSize;
isDefaultFontSize = false;
} else {
badgeParameters.badgeFontSizeByUser = false;
badgeParameters.badgeFontSize =
!fontSizeValue->IsUndefined() ? badgeTheme->GetBadgeFontSize() : UNDEFINED_DIMENSION;
}
} else {
if (ParseJsDimensionNG(fontSizeValue, fontSize, DimensionUnit::FP) && fontSize.IsNonNegative() &&
fontSize.Unit() != DimensionUnit::PERCENT) {
badgeParameters.badgeFontSize = fontSize;
isDefaultFontSize = false;
} else if (!fontSizeValue->IsUndefined()) {
badgeParameters.badgeFontSize = badgeTheme->GetBadgeFontSize();
} else {
badgeParameters.badgeFontSize = UNDEFINED_DIMENSION;
}
}
CalcDimension badgeSize;
if (SystemProperties::ConfigChangePerform()) {
RefPtr<ResourceObject> resObj;
badgeParameters.badgeCircleSizeByUser = true;
bool state = ParseJsDimensionNG(badgeSizeValue, badgeSize, DimensionUnit::FP, resObj);
badgeParameters.resourceBadgeSizeObject = resObj;
if (state && badgeSize.IsNonNegative() && badgeSize.Unit() != DimensionUnit::PERCENT) {
badgeParameters.badgeCircleSize = badgeSize;
isDefaultBadgeSize = false;
} else {
badgeParameters.badgeCircleSize = badgeTheme->GetBadgeCircleSize();
badgeParameters.badgeCircleSizeByUser = false;
}
} else {
if (ParseJsDimensionNG(badgeSizeValue, badgeSize, DimensionUnit::FP) && badgeSize.IsNonNegative() &&
badgeSize.Unit() != DimensionUnit::PERCENT) {
badgeParameters.badgeCircleSize = badgeSize;
isDefaultBadgeSize = false;
} else {
badgeParameters.badgeCircleSize = badgeTheme->GetBadgeCircleSize();
}
}
BadgeModel::GetInstance()->SetIsDefault(isDefaultFontSize, isDefaultBadgeSize);
Color color;
if (SystemProperties::ConfigChangePerform()) {
RefPtr<ResourceObject> badgeColorResObj;
badgeParameters.badgeColorByUser = false;
bool state = ParseJsColor(badgeColorValue, color, badgeColorResObj);
badgeParameters.resourceBadgeColorObject = badgeColorResObj;
if (state) {
badgeParameters.badgeColor = color;
badgeParameters.badgeColorByUser = true;
} else if (themeColors) {
badgeParameters.badgeColor = themeColors->Warning();
}
} else {
if (ParseJsColor(badgeColorValue, color)) {
badgeParameters.badgeColor = color;
} else if (themeColors) {
badgeParameters.badgeColor = themeColors->Warning();
}
}
CalcDimension borderWidth;
if (SystemProperties::ConfigChangePerform()) {
RefPtr<ResourceObject> resObj;
badgeParameters.badgeBorderWidthByUser = true;
bool state = ParseJsDimensionVp(borderWidthValue, borderWidth, resObj);
badgeParameters.resourceBorderWidthObject = resObj;
if (state && borderWidth.IsNonNegative() && borderWidth.Unit() != DimensionUnit::PERCENT) {
badgeParameters.badgeBorderWidth = borderWidth;
} else {
badgeParameters.badgeBorderWidth = badgeTheme->GetBadgeBorderWidth();
badgeParameters.badgeBorderWidthByUser = false;
}
} else {
if (ParseJsDimensionVp(borderWidthValue, borderWidth) && borderWidth.IsNonNegative() &&
borderWidth.Unit() != DimensionUnit::PERCENT) {
badgeParameters.badgeBorderWidth = borderWidth;
} else {
badgeParameters.badgeBorderWidth = badgeTheme->GetBadgeBorderWidth();
}
}
Color borderColor;
if (SystemProperties::ConfigChangePerform()) {
RefPtr<ResourceObject> borderColorResObj;
badgeParameters.badgeBorderColorByUser = false;
bool state = ParseJsColor(borderColorValue, borderColor, borderColorResObj);
badgeParameters.resourceBorderColorObject = borderColorResObj;
if (state) {
badgeParameters.badgeBorderColor = borderColor;
badgeParameters.badgeBorderColorByUser = true;
} else {
badgeParameters.badgeBorderColor =
themeColors ? themeColors->Warning() : badgeTheme->GetBadgeBorderColor();
}
} else {
if (ParseJsColor(borderColorValue, borderColor)) {
badgeParameters.badgeBorderColor = borderColor;
} else {
badgeParameters.badgeBorderColor =
themeColors ? themeColors->Warning() : badgeTheme->GetBadgeBorderColor();
}
}
CalcDimension outerBorderWidth;
if (SystemProperties::ConfigChangePerform()) {
badgeParameters.badgeOuterBorderWidthByUser = true;
badgeParameters.badgeOuterBorderColorByUser = true;
}
if (outerBorderWidthValue->IsObject()) {
JSRef<JSObject> outerBorderWidthObject = JSRef<JSObject>::Cast(outerBorderWidthValue);
if (ParseJsLengthMetricsVpWithResObj(
outerBorderWidthObject, outerBorderWidth, badgeParameters.resourceOuterBorderWidthObject)) {
badgeParameters.badgeOuterBorderWidth = outerBorderWidth;
}
} else {
badgeParameters.badgeOuterBorderWidth = badgeTheme->GetBadgeOuterBorderWidth();
badgeParameters.badgeOuterBorderWidthByUser = false;
}
Color outerBorderColor;
if (ParseJsColor(outerBorderColorValue, outerBorderColor, badgeParameters.resourceOuterBorderColorObject)) {
badgeParameters.badgeOuterBorderColor = outerBorderColor;
} else {
badgeParameters.badgeOuterBorderColor = badgeTheme->GetBadgeOuterBorderColor();
badgeParameters.badgeOuterBorderColorByUser = false;
}
if (enableAutoAvoidanceValue->IsBoolean()) {
badgeParameters.isEnableAutoAvoidance = enableAutoAvoidanceValue->ToBoolean();
} else {
badgeParameters.isEnableAutoAvoidance = false;
}
std::string fontWeight;
if (fontWeightValue->IsNumber()) {
fontWeight = std::to_string(fontWeightValue->ToNumber<int32_t>());
badgeParameters.badgeFontWeight = ConvertStrToFontWeight(fontWeight);
} else if (SystemProperties::ConfigChangePerform()) {
RefPtr<ResourceObject> resObj;
ParseJsString(fontWeightValue, fontWeight, resObj);
badgeParameters.resourceFontWeightObject = resObj;
badgeParameters.badgeFontWeight = ConvertStrToFontWeight(fontWeight);
} else {
if (!ParseJsString(fontWeightValue, fontWeight)) {
badgeParameters.badgeFontWeight = FontWeight::NORMAL;
}
badgeParameters.badgeFontWeight = ConvertStrToFontWeight(fontWeight);
}
}
auto count = obj->GetProperty("count");
if (!count->IsNull() && count->IsNumber()) {
badgeParameters.badgeCount = count->ToNumber<int32_t>();
}
auto maxCount = obj->GetProperty("maxCount");
if (!maxCount->IsNull() && maxCount->IsNumber()) {
badgeParameters.badgeMaxCount = maxCount->ToNumber<int32_t>();
} else {
badgeParameters.badgeMaxCount = badgeTheme->GetMaxCount();
}
return badgeParameters;
}
void JSBadge::JSBind(BindingTarget globalObj)
{
JSClass<JSBadge>::Declare("Badge");
MethodOptions opt = MethodOptions::NONE;
JSClass<JSBadge>::StaticMethod("create", &JSBadge::Create, opt);
JSClass<JSBadge>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
JSClass<JSBadge>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
JSClass<JSBadge>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
JSClass<JSBadge>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
JSClass<JSBadge>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
JSClass<JSBadge>::InheritAndBind<JSContainerBase>(globalObj);
}
}