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
16 #include "frameworks/bridge/declarative_frontend/jsview/js_save_button.h"
17 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
18 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
19 #endif
20
21 #include "bridge/common/utils/utils.h"
22 #include "bridge/declarative_frontend/engine/functions/js_common_utils.h"
23 #include "bridge/declarative_frontend/jsview/js_utils.h"
24 #include "core/common/container.h"
25 #include "core/components/common/properties/text_style.h"
26 #include "core/components_ng/base/view_abstract_model.h"
27 #include "core/components_ng/pattern/security_component/save_button/save_button_model_ng.h"
28 #include "core/components_ng/pattern/security_component/security_component_model_ng.h"
29 #include "core/components_ng/pattern/security_component/security_component_theme.h"
30
31 using OHOS::Ace::NG::SaveButtonModelNG;
32 using OHOS::Ace::NG::SecurityComponentModelNG;
33 using OHOS::Ace::NG::SecurityComponentTheme;
34
35 namespace OHOS::Ace::Framework {
36 using namespace OHOS::Ace::Framework::CommonUtils;
37
ParseComponentStyle(const JSCallbackInfo & info,SaveButtonSaveDescription & text,SaveButtonIconStyle & icon,int32_t & bg)38 bool JSSaveButton::ParseComponentStyle(const JSCallbackInfo& info,
39 SaveButtonSaveDescription& text, SaveButtonIconStyle& icon, int32_t& bg)
40 {
41 if ((info.Length() < 1) || (!info[0]->IsObject())) {
42 return false;
43 }
44
45 auto paramObject = JSRef<JSObject>::Cast(info[0]);
46 auto value = paramObject->GetProperty("text");
47 if (value->IsNumber()) {
48 text = static_cast<SaveButtonSaveDescription>(value->ToNumber<int32_t>());
49 if ((text < SaveButtonSaveDescription::DOWNLOAD) ||
50 (text > SaveButtonSaveDescription::MAX_LABEL_TYPE)) {
51 return false;
52 }
53 } else {
54 text = SaveButtonSaveDescription::TEXT_NULL;
55 }
56
57 value = paramObject->GetProperty("icon");
58 if (value->IsNumber()) {
59 icon = static_cast<SaveButtonIconStyle>(value->ToNumber<int32_t>());
60 if ((icon < SaveButtonIconStyle::ICON_FULL_FILLED) ||
61 (icon > SaveButtonIconStyle::ICON_PICTURE)) {
62 return false;
63 }
64 } else {
65 icon = SaveButtonIconStyle::ICON_NULL;
66 }
67
68 if ((text == SaveButtonSaveDescription::TEXT_NULL) &&
69 (icon == SaveButtonIconStyle::ICON_NULL)) {
70 return false;
71 }
72
73 value = paramObject->GetProperty("buttonType");
74 if (value->IsNumber()) {
75 bg = value->ToNumber<int32_t>();
76 if ((bg != static_cast<int32_t>(ButtonType::NORMAL)) &&
77 (bg != static_cast<int32_t>(ButtonType::CIRCLE)) &&
78 (bg != static_cast<int32_t>(ButtonType::CAPSULE)) &&
79 (bg != static_cast<int32_t>(ButtonType::ROUNDED_RECTANGLE))) {
80 return false;
81 }
82 } else {
83 bg = static_cast<int32_t>(ButtonType::CAPSULE);
84 }
85 return true;
86 }
87
Create(const JSCallbackInfo & info)88 void JSSaveButton::Create(const JSCallbackInfo& info)
89 {
90 SaveButtonSaveDescription textDesc;
91 SaveButtonIconStyle iconType;
92 int32_t backgroundType = 0;
93 if (!ParseComponentStyle(info, textDesc, iconType, backgroundType)) {
94 SaveButtonModelNG::GetInstance()->Create(
95 static_cast<int32_t>(SaveButtonSaveDescription::DOWNLOAD),
96 static_cast<int32_t>(SaveButtonIconStyle::ICON_FULL_FILLED),
97 static_cast<int32_t>(ButtonType::CAPSULE), false);
98 } else {
99 SaveButtonModelNG::GetInstance()->Create(static_cast<int32_t>(textDesc),
100 static_cast<int32_t>(iconType), backgroundType, false);
101 }
102 }
103
Execute(GestureEvent & info)104 void JsSaveButtonClickFunction::Execute(GestureEvent& info)
105 {
106 JSRef<JSObject> clickEventParam = JSRef<JSObject>::New();
107 Offset globalOffset = info.GetGlobalLocation();
108 Offset localOffset = info.GetLocalLocation();
109 Offset globalDisplayOffset = info.GetGlobalDisplayLocation();
110 clickEventParam->SetProperty<double>("screenX", PipelineBase::Px2VpWithCurrentDensity(globalOffset.GetX()));
111 clickEventParam->SetProperty<double>("screenY", PipelineBase::Px2VpWithCurrentDensity(globalOffset.GetY()));
112 clickEventParam->SetProperty<double>("x", PipelineBase::Px2VpWithCurrentDensity(localOffset.GetX()));
113 clickEventParam->SetProperty<double>("y", PipelineBase::Px2VpWithCurrentDensity(localOffset.GetY()));
114 clickEventParam->SetProperty<double>(
115 "globalDisplayX", PipelineBase::Px2VpWithCurrentDensity(globalDisplayOffset.GetX()));
116 clickEventParam->SetProperty<double>(
117 "globalDisplayY", PipelineBase::Px2VpWithCurrentDensity(globalDisplayOffset.GetY()));
118 clickEventParam->SetProperty<double>("timestamp",
119 static_cast<double>(info.GetTimeStamp().time_since_epoch().count()));
120 clickEventParam->SetProperty<double>("source", static_cast<int32_t>(info.GetSourceDevice()));
121 clickEventParam->SetProperty<double>("pressure", info.GetForce());
122 clickEventParam->SetProperty<double>("tiltX", info.GetTiltX().value_or(0.0f));
123 clickEventParam->SetProperty<double>("tiltY", info.GetTiltY().value_or(0.0f));
124 clickEventParam->SetProperty<double>("sourceTool", static_cast<int32_t>(info.GetSourceTool()));
125 auto target = CreateEventTargetObject(info);
126 clickEventParam->SetPropertyObject("target", target);
127 clickEventParam->SetProperty<int32_t>("targetDisplayId", info.GetTargetDisplayId());
128
129 int32_t res = static_cast<int32_t>(SecurityComponentHandleResult::CLICK_GRANT_FAILED);
130 JSRef<JSObject> errorMessage = JSRef<JSObject>::New();
131 #ifdef SECURITY_COMPONENT_ENABLE
132 auto secEventValue = info.GetSecCompHandleEvent();
133 if (secEventValue != nullptr) {
134 res = secEventValue->GetInt("handleRes", res);
135 int32_t code = static_cast<int32_t>(SecurityComponentErrorCode::SUCCESS);
136 std::string message;
137 if (res == static_cast<int32_t>(SecurityComponentHandleResult::DROP_CLICK)) {
138 return;
139 }
140 code = secEventValue->GetInt("code", code);
141 errorMessage->SetProperty<int32_t>("code", code);
142 message = secEventValue->GetString("message", message);
143 errorMessage->SetProperty<std::string>("message", message);
144 }
145 #endif
146 JSRef<JSVal> errorParam = JSRef<JSVal>::Make(ToJSValue(res));
147 JSRef<JSVal> params[] = { clickEventParam, errorParam, errorMessage };
148 JsFunction::ExecuteJS(3, params); // 3 means three params.
149 }
150
JsOnClick(const JSCallbackInfo & info)151 void JSSaveButton::JsOnClick(const JSCallbackInfo& info)
152 {
153 if ((info.Length() < 1) || (!info[0]->IsFunction())) {
154 return;
155 }
156 auto jsOnClickFunc = AceType::MakeRefPtr<JsSaveButtonClickFunction>(JSRef<JSFunc>::Cast(info[0]));
157 auto frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
158 auto onTap = [execCtx = info.GetExecutionContext(), func = jsOnClickFunc, node = frameNode](GestureEvent& info) {
159 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
160 ACE_SCORING_EVENT("onClick");
161 func->Execute(info);
162 #if !defined(PREVIEW) && defined(OHOS_PLATFORM)
163 JSInteractableView::ReportClickEvent(node);
164 #endif
165 };
166
167 double distanceThreshold = std::numeric_limits<double>::infinity();
168 if (info.Length() > 1 && info[1]->IsNumber()) {
169 distanceThreshold = info[1]->ToNumber<double>();
170 distanceThreshold = Dimension(distanceThreshold, DimensionUnit::VP).ConvertToPx();
171 }
172 NG::ViewAbstract::SetOnClick(std::move(onTap), distanceThreshold);
173 }
174
SetIcon(const JSCallbackInfo & info)175 void JSSaveButton::SetIcon(const JSCallbackInfo& info)
176 {
177 if (info.Length() < 1) {
178 return;
179 }
180 std::string bundleName;
181 std::string moduleName;
182 std::string src;
183 auto imageInfo = info[0];
184 int32_t resId = 0;
185 bool srcValid = ParseJsMediaWithBundleName(imageInfo, src, bundleName, moduleName, resId);
186 if (srcValid && (ImageSourceInfo::ResolveURIType(src) == SrcType::RESOURCE)) {
187 ImageSourceInfo image(std::make_shared<std::string>(src), bundleName, moduleName);
188 SecurityComponentModelNG::SetIcon(image);
189 }
190 }
191
SetText(const JSCallbackInfo & info)192 void JSSaveButton::SetText(const JSCallbackInfo& info)
193 {
194 std::string label;
195 if (info.Length() < 1) {
196 return;
197 }
198 bool parseSuccess = ParseJsString(info[0], label);
199 if (parseSuccess) {
200 if ((info[0]->IsObject() && JSRef<JSObject>::Cast(info[0])->HasProperty("id")) || (info[0]->IsString())) {
201 SecurityComponentModelNG::SetText(label);
202 }
203 }
204 }
205
SetIconBorderRadius(const JSCallbackInfo & info)206 void JSSaveButton::SetIconBorderRadius(const JSCallbackInfo& info)
207 {
208 if (info.Length() < 1) {
209 return;
210 }
211 if (info[0]->IsObject()) {
212 std::optional<CalcDimension> topLeft;
213 std::optional<CalcDimension> topRight;
214 std::optional<CalcDimension> bottomLeft;
215 std::optional<CalcDimension> bottomRight;
216 JSRef<JSObject> paddingObj = JSRef<JSObject>::Cast(info[0]);
217
218 CalcDimension topLeftDimen;
219 if (ParseJsDimensionVp(paddingObj->GetProperty("topLeft"), topLeftDimen)) {
220 topLeft = topLeftDimen;
221 }
222 CalcDimension topRightDimen;
223 if (ParseJsDimensionVp(paddingObj->GetProperty("topRight"), topRightDimen)) {
224 topRight = topRightDimen;
225 }
226 CalcDimension bottomLeftDimen;
227 if (ParseJsDimensionVp(paddingObj->GetProperty("bottomLeft"), bottomLeftDimen)) {
228 bottomLeft = bottomLeftDimen;
229 }
230 CalcDimension bottomRightDimen;
231 if (ParseJsDimensionVp(paddingObj->GetProperty("bottomRight"), bottomRightDimen)) {
232 bottomRight = bottomRightDimen;
233 }
234
235 if (topLeft.has_value() || topRight.has_value() || bottomLeft.has_value() || bottomRight.has_value()) {
236 SecurityComponentModelNG::SetIconBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
237 return;
238 }
239 }
240 auto theme = GetTheme<SecurityComponentTheme>();
241 CHECK_NULL_VOID(theme);
242
243 CalcDimension value;
244 if (!ParseJsDimensionVp(info[0], value)) {
245 SecurityComponentModelNG::SetIconBorderRadius(theme->GetBorderRadius());
246 } else {
247 SecurityComponentModelNG::SetIconBorderRadius(value);
248 }
249 }
250
SetStateEffect(const JSCallbackInfo & info)251 void JSSaveButton::SetStateEffect(const JSCallbackInfo& info)
252 {
253 if ((info.Length() < 1) || (!info[0]->IsBoolean())) {
254 return;
255 }
256 bool stateEffect = info[0]->ToBoolean();
257 SecurityComponentModelNG::SetStateEffect(stateEffect);
258 }
259
SetTipPosition(const JSCallbackInfo & info)260 void JSSaveButton::SetTipPosition(const JSCallbackInfo& info)
261 {
262 if ((info.Length() < 1) || (!info[0]->IsNumber())) {
263 SecurityComponentModelNG::SetTipPosition(TipPosition::ABOVE_BOTTOM);
264 return;
265 }
266 int32_t value = info[0]->ToNumber<int32_t>();
267 if ((value < static_cast<int32_t>(TipPosition::ABOVE_BOTTOM)) ||
268 (value > static_cast<int32_t>(TipPosition::BELOW_TOP))) {
269 SecurityComponentModelNG::SetTipPosition(TipPosition::ABOVE_BOTTOM);
270 return;
271 }
272 SecurityComponentModelNG::SetTipPosition(static_cast<TipPosition>(value));
273 }
274
JSBind(BindingTarget globalObj)275 void JSSaveButton::JSBind(BindingTarget globalObj)
276 {
277 JSClass<JSSaveButton>::Declare("SaveButton");
278 MethodOptions opt = MethodOptions::NONE;
279 JSClass<JSSaveButton>::StaticMethod("create", &JSSaveButton::Create, opt);
280 JSClass<JSSaveButton>::StaticMethod("setIcon", &JSSaveButton::SetIcon);
281 JSClass<JSSaveButton>::StaticMethod("setText", &JSSaveButton::SetText);
282 JSClass<JSSaveButton>::StaticMethod("iconSize", &JSSecButtonBase::SetIconSize);
283 JSClass<JSSaveButton>::StaticMethod("iconBorderRadius", &JSSaveButton::SetIconBorderRadius);
284 JSClass<JSSaveButton>::StaticMethod("layoutDirection", &JSSecButtonBase::SetLayoutDirection);
285 JSClass<JSSaveButton>::StaticMethod("fontSize", &JSSecButtonBase::SetFontSize);
286 JSClass<JSSaveButton>::StaticMethod("fontStyle", &JSSecButtonBase::SetFontStyle);
287 JSClass<JSSaveButton>::StaticMethod("iconColor", &JSSecButtonBase::SetIconColor);
288 JSClass<JSSaveButton>::StaticMethod("fontWeight", &JSSecButtonBase::SetFontWeight);
289 JSClass<JSSaveButton>::StaticMethod("fontFamily", &JSSecButtonBase::SetFontFamily);
290 JSClass<JSSaveButton>::StaticMethod("fontColor", &JSSecButtonBase::SetFontColor);
291 JSClass<JSSaveButton>::StaticMethod("backgroundColor", &JSSecButtonBase::SetBackgroundColor);
292 JSClass<JSSaveButton>::StaticMethod("borderStyle", &JSSecButtonBase::SetBackgroundBorderStyle);
293 JSClass<JSSaveButton>::StaticMethod("borderWidth", &JSSecButtonBase::SetBackgroundBorderWidth);
294 JSClass<JSSaveButton>::StaticMethod("borderColor", &JSSecButtonBase::SetBackgroundBorderColor);
295 JSClass<JSSaveButton>::StaticMethod("borderRadius", &JSSecButtonBase::SetBackgroundBorderRadius);
296 JSClass<JSSaveButton>::StaticMethod("padding", &JSSecButtonBase::SetBackgroundPadding);
297 JSClass<JSSaveButton>::StaticMethod("textIconSpace", &JSSecButtonBase::SetTextIconSpace);
298 JSClass<JSSaveButton>::StaticMethod("align", &JSSecButtonBase::SetAlign);
299 JSClass<JSSaveButton>::StaticMethod("onClick", &JSSaveButton::JsOnClick);
300 JSClass<JSSaveButton>::StaticMethod("stateEffect", &JSSaveButton::SetStateEffect);
301 JSClass<JSSaveButton>::StaticMethod("tipPosition", &JSSaveButton::SetTipPosition);
302 JSClass<JSSaveButton>::StaticMethod("key", &JSViewAbstract::JsKey);
303 JSClass<JSSaveButton>::StaticMethod("position", &JSViewAbstract::JsPosition);
304 JSClass<JSSaveButton>::StaticMethod("markAnchor", &JSViewAbstract::JsMarkAnchor);
305 JSClass<JSSaveButton>::StaticMethod("offset", &JSViewAbstract::JsOffset);
306 JSClass<JSSaveButton>::StaticMethod("pop", &JSViewAbstract::Pop, opt);
307 JSClass<JSSaveButton>::StaticMethod("width", &JSViewAbstract::JsWidth);
308 JSClass<JSSaveButton>::StaticMethod("height", &JSViewAbstract::JsHeight);
309 JSClass<JSSaveButton>::StaticMethod("size", &JSViewAbstract::JsSize);
310 JSClass<JSSaveButton>::StaticMethod("constraintSize", &JSViewAbstract::JsConstraintSize);
311 JSClass<JSSaveButton>::StaticMethod("debugLine", &JSViewAbstract::JsDebugLine);
312 JSClass<JSSaveButton>::StaticMethod("alignRules", &JSViewAbstract::JsAlignRules);
313 JSClass<JSSaveButton>::StaticMethod("id", &JSViewAbstract::JsId);
314 JSClass<JSSaveButton>::StaticMethod("chainMode", &JSViewAbstract::JsChainMode);
315 JSClass<JSSaveButton>::StaticMethod("maxFontScale", &JSSecButtonBase::SetMaxFontScale);
316 JSClass<JSSaveButton>::StaticMethod("minFontScale", &JSSecButtonBase::SetMinFontScale);
317 JSClass<JSSaveButton>::StaticMethod("maxLines", &JSSecButtonBase::SetMaxLines);
318 JSClass<JSSaveButton>::StaticMethod("maxFontSize", &JSSecButtonBase::SetMaxFontSize);
319 JSClass<JSSaveButton>::StaticMethod("minFontSize", &JSSecButtonBase::SetMinFontSize);
320 JSClass<JSSaveButton>::StaticMethod("heightAdaptivePolicy", &JSSecButtonBase::SetHeightAdaptivePolicy);
321 JSClass<JSSaveButton>::StaticMethod("enabled", &JSViewAbstract::JsEnabled);
322 JSClass<JSSaveButton>::Bind<>(globalObj);
323 }
324 } // namespace OHOS::Ace::Framework
325