1 /*
2 * Copyright (c) 2021-2025 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_search.h"
17
18 #include <optional>
19 #include <string>
20 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
21
22 #include "base/log/ace_scoring_log.h"
23 #include "bridge/declarative_frontend/engine/functions/js_clipboard_function.h"
24 #include "bridge/declarative_frontend/engine/functions/js_common_event_function.h"
25 #include "bridge/declarative_frontend/engine/functions/js_cited_event_function.h"
26 #include "bridge/declarative_frontend/engine/functions/js_event_function.h"
27 #include "bridge/declarative_frontend/engine/jsi/js_ui_index.h"
28 #include "bridge/declarative_frontend/jsview/js_text_editable_controller.h"
29 #include "bridge/declarative_frontend/jsview/js_textfield.h"
30 #include "bridge/declarative_frontend/jsview/js_textinput.h"
31 #include "bridge/declarative_frontend/jsview/js_view_abstract.h"
32 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
33 #include "bridge/declarative_frontend/jsview/models/search_model_impl.h"
34 #include "core/components/common/layout/constants.h"
35 #include "core/components/common/properties/text_style_parser.h"
36 #include "core/components/search/search_theme.h"
37 #include "core/components_ng/gestures/gesture_info.h"
38 #include "core/components_ng/pattern/search/search_model_ng.h"
39 #include "core/components_ng/pattern/text_field/text_field_model_ng.h"
40
41 namespace OHOS::Ace {
42
43 std::unique_ptr<SearchModel> SearchModel::instance_ = nullptr;
44 std::mutex SearchModel::mutex_;
45
GetInstance()46 SearchModel* SearchModel::GetInstance()
47 {
48 #ifdef NG_BUILD
49 static NG::SearchModelNG instance;
50 return &instance;
51 #else
52 if (Container::IsCurrentUseNewPipeline()) {
53 static NG::SearchModelNG instance;
54 return &instance;
55 } else {
56 static Framework::SearchModelImpl instance;
57 return &instance;
58 }
59 #endif
60 }
61
62 } // namespace OHOS::Ace
63
64 namespace OHOS::Ace::Framework {
65 namespace {
66 const std::vector<TextAlign> TEXT_ALIGNS = { TextAlign::START, TextAlign::CENTER, TextAlign::END };
67 constexpr double DEFAULT_OPACITY = 0.2;
68 const int32_t DEFAULT_ALPHA = 255;
69 constexpr TextDecorationStyle DEFAULT_TEXT_DECORATION_STYLE = TextDecorationStyle::SOLID;
70 const char* TOP_START_PROPERTY = "topStart";
71 const char* TOP_END_PROPERTY = "topEnd";
72 const char* BOTTOM_START_PROPERTY = "bottomStart";
73 const char* BOTTOM_END_PROPERTY = "bottomEnd";
74
ParseJsLengthMetrics(const JSRef<JSObject> & obj,CalcDimension & result)75 bool ParseJsLengthMetrics(const JSRef<JSObject>& obj, CalcDimension& result)
76 {
77 auto value = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::VALUE));
78 if (!value->IsNumber()) {
79 return false;
80 }
81 auto unit = DimensionUnit::VP;
82 auto jsUnit = obj->GetProperty(static_cast<int32_t>(ArkUIIndex::UNIT));
83 if (jsUnit->IsNumber()) {
84 unit = static_cast<DimensionUnit>(jsUnit->ToNumber<int32_t>());
85 }
86 CalcDimension dimension(value->ToNumber<double>(), unit);
87 result = dimension;
88 return true;
89 }
90 } // namespace
91
JSBind(BindingTarget globalObj)92 void JSSearch::JSBind(BindingTarget globalObj)
93 {
94 JSClass<JSSearch>::Declare("Search");
95 MethodOptions opt = MethodOptions::NONE;
96
97 JSClass<JSSearch>::StaticMethod("create", &JSSearch::Create, opt);
98 JSClass<JSSearch>::StaticMethod("searchButton", &JSSearch::SetSearchButton, opt);
99 JSClass<JSSearch>::StaticMethod("searchIcon", &JSSearch::SetSearchIcon, opt);
100 JSClass<JSSearch>::StaticMethod("cancelButton", &JSSearch::SetCancelButton, opt);
101 JSClass<JSSearch>::StaticMethod("fontColor", &JSSearch::SetTextColor, opt);
102 JSClass<JSSearch>::StaticMethod("backgroundColor", &JSSearch::SetBackgroundColor, opt);
103 JSClass<JSSearch>::StaticMethod("caretStyle", &JSSearch::SetCaret, opt);
104 JSClass<JSSearch>::StaticMethod("placeholderColor", &JSSearch::SetPlaceholderColor, opt);
105 JSClass<JSSearch>::StaticMethod("placeholderFont", &JSSearch::SetPlaceholderFont, opt);
106 JSClass<JSSearch>::StaticMethod("textFont", &JSSearch::SetTextFont, opt);
107 JSClass<JSSearch>::StaticMethod("textAlign", &JSSearch::SetTextAlign, opt);
108 JSClass<JSSearch>::StaticMethod("onSubmit", &JSSearch::OnSubmit, opt);
109 JSClass<JSSearch>::StaticMethod("onChange", &JSSearch::OnChange, opt);
110 JSClass<JSSearch>::StaticMethod("onTextSelectionChange", &JSSearch::SetOnTextSelectionChange);
111 JSClass<JSSearch>::StaticMethod("onContentScroll", &JSSearch::SetOnScroll);
112 JSClass<JSSearch>::StaticMethod("border", &JSSearch::JsBorder);
113 JSClass<JSSearch>::StaticMethod("borderWidth", &JSSearch::JsBorderWidth);
114 JSClass<JSSearch>::StaticMethod("borderColor", &JSSearch::JsBorderColor);
115 JSClass<JSSearch>::StaticMethod("borderStyle", &JSSearch::JsBorderStyle);
116 JSClass<JSSearch>::StaticMethod("borderRadius", &JSSearch::JsBorderRadius);
117 JSClass<JSSearch>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
118 JSClass<JSSearch>::StaticMethod("height", &JSSearch::SetHeight);
119 JSClass<JSSearch>::StaticMethod("width", &JSViewAbstract::JsWidth);
120 JSClass<JSSearch>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
121 JSClass<JSSearch>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
122 JSClass<JSSearch>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
123 JSClass<JSSearch>::StaticMethod("requestKeyboardOnFocus", &JSSearch::SetEnableKeyboardOnFocus);
124 JSClass<JSSearch>::StaticMethod("enableKeyboardOnFocus", &JSSearch::SetEnableKeyboardOnFocus);
125 JSClass<JSSearch>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
126 JSClass<JSSearch>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
127 JSClass<JSSearch>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
128 JSClass<JSSearch>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
129 JSClass<JSSearch>::StaticMethod("onCopy", &JSSearch::SetOnCopy);
130 JSClass<JSSearch>::StaticMethod("onCut", &JSSearch::SetOnCut);
131 JSClass<JSSearch>::StaticMethod("onPaste", &JSSearch::SetOnPaste);
132 JSClass<JSSearch>::StaticMethod("copyOption", &JSSearch::SetCopyOption);
133 JSClass<JSSearch>::StaticMethod("selectionMenuHidden", &JSSearch::SetSelectionMenuHidden);
134 JSClass<JSSearch>::StaticMethod("customKeyboard", &JSSearch::SetCustomKeyboard);
135 JSClass<JSSearch>::StaticMethod("enterKeyType", &JSSearch::SetEnterKeyType);
136 JSClass<JSSearch>::StaticMethod("maxLength", &JSSearch::SetMaxLength);
137 JSClass<JSSearch>::StaticMethod("type", &JSSearch::SetType);
138 JSClass<JSSearch>::StaticMethod("dragPreviewOptions", &JSSearch::SetDragPreviewOptions);
139 JSClass<JSSearch>::StaticMethod("editMenuOptions", &JSSearch::EditMenuOptions);
140 JSClass<JSSearch>::StaticMethod("strokeWidth", &JSSearch::SetStrokeWidth);
141 JSClass<JSSearch>::StaticMethod("strokeColor", &JSSearch::SetStrokeColor);
142 JSClass<JSSearch>::StaticMethod("margin", &JSSearch::JsMargin);
143 JSBindMore();
144 JSClass<JSSearch>::InheritAndBind<JSViewAbstract>(globalObj);
145 }
146
JSBindMore()147 void JSSearch::JSBindMore()
148 {
149 JSClass<JSSearch>::StaticMethod("decoration", &JSSearch::SetDecoration);
150 JSClass<JSSearch>::StaticMethod("minFontSize", &JSSearch::SetMinFontSize);
151 JSClass<JSSearch>::StaticMethod("maxFontSize", &JSSearch::SetMaxFontSize);
152 JSClass<JSSearch>::StaticMethod("minFontScale", &JSSearch::SetMinFontScale);
153 JSClass<JSSearch>::StaticMethod("maxFontScale", &JSSearch::SetMaxFontScale);
154 JSClass<JSSearch>::StaticMethod("letterSpacing", &JSSearch::SetLetterSpacing);
155 JSClass<JSSearch>::StaticMethod("lineHeight", &JSSearch::SetLineHeight);
156 JSClass<JSSearch>::StaticMethod("halfLeading", &JSSearch::SetHalfLeading);
157 JSClass<JSSearch>::StaticMethod("fontFeature", &JSSearch::SetFontFeature);
158 JSClass<JSSearch>::StaticMethod("id", &JSSearch::SetId);
159 JSClass<JSSearch>::StaticMethod("key", &JSSearch::SetKey);
160 JSClass<JSSearch>::StaticMethod("selectedBackgroundColor", &JSSearch::SetSelectedBackgroundColor);
161 JSClass<JSSearch>::StaticMethod("inputFilter", &JSSearch::SetInputFilter);
162 JSClass<JSSearch>::StaticMethod("onEditChange", &JSSearch::SetOnEditChange);
163 JSClass<JSSearch>::StaticMethod("textIndent", &JSSearch::SetTextIndent);
164 JSClass<JSSearch>::StaticMethod("onWillInsert", &JSSearch::OnWillInsertValue);
165 JSClass<JSSearch>::StaticMethod("onDidInsert", &JSSearch::OnDidInsertValue);
166 JSClass<JSSearch>::StaticMethod("onWillDelete", &JSSearch::OnWillDelete);
167 JSClass<JSSearch>::StaticMethod("onDidDelete", &JSSearch::OnDidDelete);
168 JSClass<JSSearch>::StaticMethod("enablePreviewText", &JSSearch::SetEnablePreviewText);
169 JSClass<JSSearch>::StaticMethod("enableHapticFeedback", &JSSearch::SetEnableHapticFeedback);
170 JSClass<JSSearch>::StaticMethod("autoCapitalizationMode", &JSSearch::SetCapitalizationMode);
171 JSClass<JSSearch>::StaticMethod("stopBackPress", &JSSearch::SetStopBackPress);
172 JSClass<JSSearch>::StaticMethod("keyboardAppearance", &JSSearch::SetKeyboardAppearance);
173 JSClass<JSSearch>::StaticMethod("onWillChange", &JSSearch::SetOnWillChange);
174 JSClass<JSSearch>::StaticMethod("enableAutoSpacing", &JSSearch::SetEnableAutoSpacing);
175 JSClass<JSSearch>::StaticMethod("onWillAttachIME", &JSSearch::SetOnWillAttachIME);
176 }
177
ParseSearchValueObject(const JSCallbackInfo & info,const JSRef<JSVal> & changeEventVal)178 void ParseSearchValueObject(const JSCallbackInfo& info, const JSRef<JSVal>& changeEventVal)
179 {
180 CHECK_NULL_VOID(changeEventVal->IsFunction());
181
182 JsEventCallback<void(const std::u16string&)> onChangeEvent(
183 info.GetExecutionContext(), JSRef<JSFunc>::Cast(changeEventVal));
184 SearchModel::GetInstance()->SetOnChangeEvent(std::move(onChangeEvent));
185 }
186
SetDragPreviewOptions(const JSCallbackInfo & info)187 void JSSearch::SetDragPreviewOptions(const JSCallbackInfo& info)
188 {
189 NG::DragPreviewOption option = JSViewAbstract::ParseDragPreviewOptions(info);
190 SearchModel::GetInstance()->SetDragPreviewOptions(option);
191 }
192
SetFontFeature(const JSCallbackInfo & info)193 void JSSearch::SetFontFeature(const JSCallbackInfo& info)
194 {
195 if (info.Length() < 1) {
196 return;
197 }
198
199 if (!info[0]->IsString() && !info[0]->IsObject()) {
200 return;
201 }
202 std::string fontFeatureSettings = info[0]->ToString();
203 SearchModel::GetInstance()->SetFontFeature(ParseFontFeatureSettings(fontFeatureSettings));
204 }
205
Create(const JSCallbackInfo & info)206 void JSSearch::Create(const JSCallbackInfo& info)
207 {
208 std::optional<std::u16string> key;
209 std::optional<std::u16string> tip;
210 std::optional<std::string> src;
211 JSTextEditableController* jsController = nullptr;
212 JSRef<JSVal> changeEventVal;
213 bool placeholderResult = false;
214 bool textResult = false;
215 std::u16string placeholder;
216 std::u16string text;
217 RefPtr<ResourceObject> placeholderObject;
218 RefPtr<ResourceObject> textObject;
219 if (info[0]->IsObject()) {
220 auto param = JSRef<JSObject>::Cast(info[0]);
221 if (param->GetProperty("placeholder")->IsUndefined()) {
222 tip = u"";
223 }
224 placeholderResult = ParseJsString(param->GetProperty("placeholder"), placeholder, placeholderObject);
225 if (placeholderResult) {
226 tip = placeholder;
227 }
228
229 JSRef<JSVal> textValue = param->GetProperty("value");
230 if (textValue->IsObject()) {
231 JSRef<JSObject> valueObj = JSRef<JSObject>::Cast(textValue);
232 changeEventVal = valueObj->GetProperty("changeEvent");
233 if (changeEventVal->IsFunction()) {
234 textValue = valueObj->GetProperty("value");
235 }
236 textResult = ParseJsString(textValue, text, textObject);
237 if (textResult) {
238 key = text;
239 }
240 } else if (param->GetProperty("$value")->IsFunction()) {
241 changeEventVal = param->GetProperty("$value");
242 textResult = ParseJsString(textValue, text, textObject);
243 if (textResult) {
244 key = text;
245 }
246 } else if (param->HasProperty("value") && textValue->IsUndefined()) {
247 key = u"";
248 } else {
249 textResult = ParseJsString(textValue, text, textObject);
250 if (textResult) {
251 key = text;
252 }
253 }
254 std::string icon;
255 if (ParseJsString(param->GetProperty("icon"), icon)) {
256 src = icon;
257 }
258 auto controllerObj = param->GetProperty("controller");
259 if (!controllerObj->IsUndefined() && !controllerObj->IsNull() && controllerObj->IsObject()) {
260 jsController = JSRef<JSObject>::Cast(controllerObj)->Unwrap<JSTextEditableController>();
261 }
262 }
263 auto controller = SearchModel::GetInstance()->Create(key, tip, src);
264 if (jsController) {
265 jsController->SetController(controller);
266 }
267 SearchModel::GetInstance()->SetFocusable(true);
268 SearchModel::GetInstance()->SetFocusNode(true);
269 if (!changeEventVal->IsUndefined() && changeEventVal->IsFunction()) {
270 ParseSearchValueObject(info, changeEventVal);
271 }
272 if (SystemProperties::ConfigChangePerform()) {
273 if (placeholderResult && placeholderObject) {
274 RegisterResource<std::u16string>("placeholder", placeholderObject, placeholder);
275 } else {
276 UnregisterResource("placeholder");
277 }
278 }
279
280 if (SystemProperties::ConfigChangePerform()) {
281 if (textResult && textObject) {
282 RegisterResource<std::u16string>("text", textObject, text);
283 } else {
284 UnregisterResource("text");
285 }
286 }
287 }
288
SetSelectedBackgroundColor(const JSCallbackInfo & info)289 void JSSearch::SetSelectedBackgroundColor(const JSCallbackInfo& info)
290 {
291 if (info.Length() < 1) {
292 return;
293 }
294 Color selectedColor;
295 RefPtr<ResourceObject> resourceObject;
296 UnregisterResource("selectedBackgroundColor");
297 if (!ParseJsColor(info[0], selectedColor, resourceObject)) {
298 SearchModel::GetInstance()->ResetSelectedBackgroundColor();
299 return;
300 }
301 if (SystemProperties::ConfigChangePerform() && resourceObject) {
302 RegisterResource<Color>("selectedBackgroundColor", resourceObject, selectedColor);
303 }
304 // Alpha = 255 means opaque
305 if (selectedColor.GetAlpha() == DEFAULT_ALPHA) {
306 // Default setting of 20% opacity
307 selectedColor = selectedColor.ChangeOpacity(DEFAULT_OPACITY);
308 }
309 SearchModel::GetInstance()->SetSelectedBackgroundColor(selectedColor);
310 }
311
SetEnableKeyboardOnFocus(const JSCallbackInfo & info)312 void JSSearch::SetEnableKeyboardOnFocus(const JSCallbackInfo& info)
313 {
314 if (info[0]->IsUndefined() || !info[0]->IsBoolean()) {
315 SearchModel::GetInstance()->RequestKeyboardOnFocus(true);
316 return;
317 }
318 SearchModel::GetInstance()->RequestKeyboardOnFocus(info[0]->ToBoolean());
319 }
320
SetId(const JSCallbackInfo & info)321 void JSSearch::SetId(const JSCallbackInfo& info)
322 {
323 JSViewAbstract::JsId(info);
324 JSRef<JSVal> arg = info[0];
325 std::string id;
326 if (arg->IsString()) {
327 id = arg->ToString();
328 }
329 SearchModel::GetInstance()->UpdateInspectorId(id);
330 }
331
SetKey(const std::string & key)332 void JSSearch::SetKey(const std::string& key)
333 {
334 JSViewAbstract::JsKey(key);
335 SearchModel::GetInstance()->UpdateInspectorId(key);
336 }
337
SetSearchButtonOptions(const JSCallbackInfo & info)338 void JSSearch::SetSearchButtonOptions(const JSCallbackInfo& info)
339 {
340 auto theme = GetTheme<SearchTheme>();
341 CHECK_NULL_VOID(theme);
342 Color fontColor = theme->GetSearchButtonTextColor();
343 if (info.Length() < 2 || !info[1]->IsObject()) { // 2 : args num
344 SearchModel::GetInstance()->SetSearchButtonFontSize(theme->GetButtonFontSize());
345 SearchModel::GetInstance()->ResetSearchButtonFontColor();
346 return;
347 }
348
349 auto param = JSRef<JSObject>::Cast(info[1]);
350 // set button font size, unit FP
351 auto fontSize = param->GetProperty("fontSize");
352 RefPtr<ResourceObject> fontSizeObject;
353 UnregisterResource("searchButtonFontSize");
354 CalcDimension size = theme->GetButtonFontSize();
355 if (ParseJsDimensionVpNG(fontSize, size, fontSizeObject) && size.Unit() != DimensionUnit::PERCENT &&
356 GreatOrEqual(size.Value(), 0.0)) {
357 ParseJsDimensionFp(fontSize, size, fontSizeObject);
358 } else {
359 size = theme->GetButtonFontSize();
360 }
361 if (SystemProperties::ConfigChangePerform() && fontSizeObject) {
362 RegisterResource<CalcDimension>("searchButtonFontSize", fontSizeObject, size);
363 }
364 SearchModel::GetInstance()->SetSearchButtonFontSize(size);
365
366 auto fontColorProp = param->GetProperty("fontColor");
367 RefPtr<ResourceObject> colorObject;
368 UnregisterResource("searchButtonFontColor");
369 if (fontColorProp->IsUndefined() || fontColorProp->IsNull() ||
370 !ParseJsColor(fontColorProp, fontColor, colorObject)) {
371 SearchModel::GetInstance()->ResetSearchButtonFontColor();
372 } else {
373 SearchModel::GetInstance()->SetSearchButtonFontColor(fontColor);
374 }
375 if (SystemProperties::ConfigChangePerform() && colorObject) {
376 RegisterResource<Color>("searchButtonFontColor", colorObject, fontColor);
377 }
378
379 auto autoDisable = param->GetProperty("autoDisable");
380 if (autoDisable->IsUndefined() || autoDisable->IsNull() || !autoDisable->IsBoolean()) {
381 SearchModel::GetInstance()->SetSearchButtonAutoDisable(false);
382 } else {
383 SearchModel::GetInstance()->SetSearchButtonAutoDisable(autoDisable->ToBoolean());
384 }
385 }
386
SetSearchButton(const JSCallbackInfo & info)387 void JSSearch::SetSearchButton(const JSCallbackInfo& info)
388 {
389 auto theme = GetTheme<SearchTheme>();
390 CHECK_NULL_VOID(theme);
391 std::string buttonValue = "";
392 UnregisterResource("searchButtonValue");
393 if (info[0]->IsString()) {
394 buttonValue = info[0]->ToString();
395 } else {
396 RefPtr<ResourceObject> resourceObject;
397 ParseJsString(info[0], buttonValue, resourceObject);
398 if (SystemProperties::ConfigChangePerform() && resourceObject) {
399 RegisterResource<std::string>("searchButtonValue", resourceObject, buttonValue);
400 }
401 }
402 SearchModel::GetInstance()->SetSearchButton(buttonValue);
403 SetSearchButtonOptions(info);
404 }
405
SetSearchIcon(const JSCallbackInfo & info)406 void JSSearch::SetSearchIcon(const JSCallbackInfo& info)
407 {
408 if (SystemProperties::ConfigChangePerform()) {
409 UnregisterResource("searchIconSize");
410 UnregisterResource("searchButtonIconSrc");
411 UnregisterResource("searchIconColor");
412 }
413 if (info[0]->IsUndefined() || info[0]->IsNull()) {
414 SetSearchDefaultIcon();
415 return;
416 }
417 if (info[0]->IsObject()) {
418 auto param = JSRef<JSObject>::Cast(info[0]);
419 bool isSymbolIcon = param->HasProperty("fontColor"); // only SymbolGlyph has fontColor property
420 if (isSymbolIcon) {
421 SetSearchSymbolIcon(info);
422 } else {
423 SetSearchImageIcon(info);
424 }
425 }
426 }
427
SetCancelDefaultIcon()428 void JSSearch::SetCancelDefaultIcon()
429 {
430 SearchModel::GetInstance()->SetCancelDefaultIcon();
431 }
432
SetCancelSymbolIcon(const JSCallbackInfo & info)433 void JSSearch::SetCancelSymbolIcon(const JSCallbackInfo& info)
434 {
435 if (info[0]->IsObject()) {
436 std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
437 auto param = JSRef<JSObject>::Cast(info[0]);
438 auto iconProp = param->GetProperty("icon");
439 SetSymbolOptionApply(info, iconSymbol, iconProp);
440 SearchModel::GetInstance()->SetCancelSymbolIcon(iconSymbol);
441 }
442 }
443
SetCancelImageIcon(const JSCallbackInfo & info)444 void JSSearch::SetCancelImageIcon(const JSCallbackInfo& info)
445 {
446 if (!info[0]->IsObject()) {
447 return;
448 }
449 auto param = JSRef<JSObject>::Cast(info[0]);
450 auto theme = GetTheme<SearchTheme>();
451 CHECK_NULL_VOID(theme);
452 auto iconJsVal = param->GetProperty("icon");
453 if (!iconJsVal->IsObject()) {
454 return;
455 }
456 auto iconParam = JSRef<JSObject>::Cast(iconJsVal);
457
458 // set icon size
459 CalcDimension iconSize;
460 auto iconSizeProp = iconParam->GetProperty("size");
461 RefPtr<ResourceObject> sizeObject;
462 UnregisterResource("cancelButtonIconSize");
463 if (!iconSizeProp->IsUndefined() && !iconSizeProp->IsNull() &&
464 ParseJsDimensionVpNG(iconSizeProp, iconSize, sizeObject)) {
465 if (LessNotEqual(iconSize.Value(), 0.0) || iconSize.Unit() == DimensionUnit::PERCENT) {
466 iconSize = theme->GetIconHeight();
467 }
468 } else {
469 iconSize = theme->GetIconHeight();
470 }
471 if (SystemProperties::ConfigChangePerform() && sizeObject) {
472 RegisterResource<CalcDimension>("cancelButtonIconSize", sizeObject, iconSize);
473 }
474
475 // set icon src
476 std::string iconSrc;
477 RefPtr<ResourceObject> srcObject;
478 UnregisterResource("cancelButtonIconSrc");
479 auto iconSrcProp = iconParam->GetProperty("src");
480 if (iconSrcProp->IsUndefined() || iconSrcProp->IsNull() || !ParseJsMedia(iconSrcProp, iconSrc, srcObject)) {
481 iconSrc = "";
482 }
483 if (SystemProperties::ConfigChangePerform() && srcObject) {
484 RegisterResource<std::string>("cancelButtonIconSrc", srcObject, iconSrc);
485 }
486
487 // set icon color
488 Color iconColor;
489 RefPtr<ResourceObject> colorObject;
490 UnregisterResource("cancelButtonIconColor");
491 NG::IconOptions cancelIconOptions;
492 auto iconColorProp = iconParam->GetProperty("color");
493 if (!iconColorProp->IsUndefined() && !iconColorProp->IsNull() &&
494 ParseJsColor(iconColorProp, iconColor, colorObject)) {
495 SearchModel::GetInstance()->SetCancelIconColor(iconColor);
496 cancelIconOptions = NG::IconOptions(iconColor, iconSize, iconSrc, "", "");
497 } else {
498 SearchModel::GetInstance()->ResetCancelIconColor();
499 cancelIconOptions = NG::IconOptions(iconSize, iconSrc, "", "");
500 }
501 if (SystemProperties::ConfigChangePerform() && colorObject) {
502 RegisterResource<Color>("cancelButtonIconColor", colorObject, iconColor);
503 }
504 SearchModel::GetInstance()->SetCancelImageIcon(cancelIconOptions);
505 }
506
SetSearchDefaultIcon()507 void JSSearch::SetSearchDefaultIcon()
508 {
509 SearchModel::GetInstance()->SetSearchDefaultIcon();
510 }
511
SetSearchSymbolIcon(const JSCallbackInfo & info)512 void JSSearch::SetSearchSymbolIcon(const JSCallbackInfo& info)
513 {
514 if (!info[0]->IsObject()) {
515 return;
516 }
517
518 std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
519 SetSymbolOptionApply(info, iconSymbol, info[0]);
520 SearchModel::GetInstance()->SetSearchSymbolIcon(iconSymbol);
521 }
522
SetSearchImageIcon(const JSCallbackInfo & info)523 void JSSearch::SetSearchImageIcon(const JSCallbackInfo& info)
524 {
525 if (!info[0]->IsObject()) {
526 return;
527 }
528 auto param = JSRef<JSObject>::Cast(info[0]);
529 auto theme = GetTheme<SearchTheme>();
530 CHECK_NULL_VOID(theme);
531
532 // set icon size
533 CalcDimension size;
534 auto sizeProp = param->GetProperty("size");
535 RefPtr<ResourceObject> sizeObject;
536 if (!sizeProp->IsUndefined() && !sizeProp->IsNull() &&
537 ParseJsDimensionVpNG(sizeProp, size, sizeObject)) {
538 if (LessNotEqual(size.Value(), 0.0) || size.Unit() == DimensionUnit::PERCENT) {
539 size = theme->GetIconHeight();
540 }
541 } else {
542 size = theme->GetIconHeight();
543 }
544 if (SystemProperties::ConfigChangePerform() && sizeObject) {
545 RegisterResource<CalcDimension>("searchIconSize", sizeObject, size);
546 }
547 // set icon src
548 std::string src;
549 RefPtr<ResourceObject> mediaObject;
550 auto srcPathProp = param->GetProperty("src");
551 if (srcPathProp->IsUndefined() || srcPathProp->IsNull() || !ParseJsMedia(srcPathProp, src, mediaObject)) {
552 src = "";
553 }
554 if (SystemProperties::ConfigChangePerform() && mediaObject) {
555 RegisterResource<std::string>("searchButtonIconSrc", mediaObject, src);
556 }
557 std::string bundleName;
558 std::string moduleName;
559 GetJsMediaBundleInfo(srcPathProp, bundleName, moduleName);
560 // set icon color
561 Color colorVal;
562 RefPtr<ResourceObject> colorObject;
563 NG::IconOptions searchIconOptions;
564 auto colorProp = param->GetProperty("color");
565 if (!colorProp->IsUndefined() && !colorProp->IsNull() && ParseJsColor(colorProp, colorVal, colorObject)) {
566 SearchModel::GetInstance()->SetSearchIconColor(colorVal);
567 searchIconOptions = NG::IconOptions(colorVal, size, src, bundleName, moduleName);
568 } else {
569 SearchModel::GetInstance()->ResetSearchIconColor();
570 searchIconOptions = NG::IconOptions(size, src, bundleName, moduleName);
571 }
572 if (SystemProperties::ConfigChangePerform() && colorObject) {
573 RegisterResource<Color>("searchIconColor", colorObject, colorVal);
574 }
575 SearchModel::GetInstance()->SetSearchImageIcon(searchIconOptions);
576 }
577
ConvertStrToCancelButtonStyle(const std::string & value)578 static CancelButtonStyle ConvertStrToCancelButtonStyle(const std::string& value)
579 {
580 if (value == "CONSTANT") {
581 return CancelButtonStyle::CONSTANT;
582 } else if (value == "INVISIBLE") {
583 return CancelButtonStyle::INVISIBLE;
584 } else {
585 return CancelButtonStyle::INPUT;
586 }
587 }
588
SetCancelButton(const JSCallbackInfo & info)589 void JSSearch::SetCancelButton(const JSCallbackInfo& info)
590 {
591 if (!info[0]->IsObject()) {
592 return;
593 }
594 auto param = JSRef<JSObject>::Cast(info[0]);
595 auto theme = GetTheme<SearchTheme>();
596 CHECK_NULL_VOID(theme);
597
598 // set style
599 std::string styleStr;
600 CancelButtonStyle cancelButtonStyle;
601 auto styleProp = param->GetProperty("style");
602 if (!styleProp->IsUndefined() && !styleProp->IsNull() && ParseJsString(styleProp, styleStr)) {
603 cancelButtonStyle = ConvertStrToCancelButtonStyle(styleStr);
604 } else {
605 cancelButtonStyle = theme->GetCancelButtonStyle();
606 }
607 SearchModel::GetInstance()->SetCancelButtonStyle(cancelButtonStyle);
608
609 auto iconProp = param->GetProperty("icon");
610 if (iconProp->IsUndefined() || iconProp->IsNull()) {
611 SetCancelDefaultIcon();
612 } else {
613 SetIconStyle(info);
614 }
615 }
616
SetIconStyle(const JSCallbackInfo & info)617 void JSSearch::SetIconStyle(const JSCallbackInfo& info)
618 {
619 if (!info[0]->IsObject()) {
620 return;
621 }
622
623 auto param = JSRef<JSObject>::Cast(info[0]);
624 auto iconJsVal = param->GetProperty("icon");
625 if (!iconJsVal->IsObject()) {
626 return;
627 }
628
629 auto iconParam = JSRef<JSObject>::Cast(iconJsVal);
630 bool isSymbolIcon = iconParam->HasProperty("fontColor"); // only SymbolGlyph has fontColor property
631 if (isSymbolIcon) {
632 SetCancelSymbolIcon(info);
633 } else {
634 SetCancelImageIcon(info);
635 }
636 }
637
SetTextColor(const JSCallbackInfo & info)638 void JSSearch::SetTextColor(const JSCallbackInfo& info)
639 {
640 auto theme = GetTheme<SearchTheme>();
641 CHECK_NULL_VOID(theme);
642
643 auto value = JSRef<JSVal>::Cast(info[0]);
644 Color colorVal;
645 RefPtr<ResourceObject> resourceObject;
646 UnregisterResource("fontColor");
647 if (!ParseJsColor(value, colorVal, resourceObject)) {
648 SearchModel::GetInstance()->ResetTextColor();
649 return;
650 }
651 if (SystemProperties::ConfigChangePerform() && resourceObject) {
652 RegisterResource<Color>("fontColor", resourceObject, colorVal);
653 }
654 SearchModel::GetInstance()->SetTextColor(colorVal);
655 }
656
SetBackgroundColor(const JSCallbackInfo & info)657 void JSSearch::SetBackgroundColor(const JSCallbackInfo& info)
658 {
659 if (info.Length() < 1) {
660 return;
661 }
662 Color colorVal;
663 if (!ParseJsColor(info[0], colorVal)) {
664 SearchModel::GetInstance()->ResetBackgroundColor();
665 return;
666 }
667 SearchModel::GetInstance()->SetBackgroundColor(colorVal);
668 }
669
SetCaret(const JSCallbackInfo & info)670 void JSSearch::SetCaret(const JSCallbackInfo& info)
671 {
672 if (info[0]->IsObject()) {
673 auto param = JSRef<JSObject>::Cast(info[0]);
674 auto textFieldTheme = GetTheme<TextFieldTheme>();
675 CHECK_NULL_VOID(textFieldTheme);
676
677 // set caret width
678 CalcDimension caretWidth = textFieldTheme->GetCursorWidth();
679 auto caretWidthProp = param->GetProperty("width");
680 RefPtr<ResourceObject> widthObject;
681 UnregisterResource("caretWidth");
682 if (!ParseJsDimensionVpNG(caretWidthProp, caretWidth, widthObject, false) ||
683 LessNotEqual(caretWidth.Value(), 0.0)) {
684 caretWidth = textFieldTheme->GetCursorWidth();
685 }
686 if (SystemProperties::ConfigChangePerform() && widthObject) {
687 RegisterResource<CalcDimension>("caretWidth", widthObject, caretWidth);
688 }
689 SearchModel::GetInstance()->SetCaretWidth(caretWidth);
690
691 // set caret color
692 Color caretColor;
693 RefPtr<ResourceObject> colorObject;
694 UnregisterResource("caretColor");
695 auto caretColorProp = param->GetProperty("color");
696 if (caretColorProp->IsUndefined() || caretColorProp->IsNull() ||
697 !ParseJsColor(caretColorProp, caretColor, colorObject)) {
698 SearchModel::GetInstance()->ResetCaretColor();
699 return;
700 }
701 if (SystemProperties::ConfigChangePerform() && colorObject) {
702 RegisterResource<Color>("caretColor", colorObject, caretColor);
703 }
704 SearchModel::GetInstance()->SetCaretColor(caretColor);
705 }
706 }
707
SetInputFilter(const JSCallbackInfo & info)708 void JSSearch::SetInputFilter(const JSCallbackInfo& info)
709 {
710 if (info.Length() < 1) {
711 return;
712 }
713 auto tmpInfo = info[0];
714 auto errInfo = info[1];
715 std::string inputFilter;
716 if (tmpInfo->IsUndefined()) {
717 UnregisterResource("inputFilter");
718 SearchModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
719 return;
720 }
721
722 RefPtr<ResourceObject> resourceObject;
723 if (!ParseJsString(tmpInfo, inputFilter, resourceObject)) {
724 return;
725 }
726 if (SystemProperties::ConfigChangePerform() && resourceObject) {
727 RegisterResource<std::string>("inputFilter", resourceObject, inputFilter);
728 } else {
729 UnregisterResource("inputFilter");
730 }
731
732 if (!CheckRegexValid(inputFilter)) {
733 inputFilter = "";
734 }
735 if (info.Length() > 1 && errInfo->IsFunction()) {
736 auto jsFunc = AceType::MakeRefPtr<JsClipboardFunction>(JSRef<JSFunc>::Cast(errInfo));
737 auto targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
738 auto resultId = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
739 const std::u16string& info) {
740 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
741 PipelineContext::SetCallBackNode(node);
742 func->Execute(info);
743 };
744 SearchModel::GetInstance()->SetInputFilter(inputFilter, resultId);
745 return;
746 }
747 SearchModel::GetInstance()->SetInputFilter(inputFilter, nullptr);
748 }
749
SetOnEditChange(const JSCallbackInfo & info)750 void JSSearch::SetOnEditChange(const JSCallbackInfo& info)
751 {
752 auto tmpInfo = info[0];
753 CHECK_NULL_VOID(tmpInfo->IsFunction());
754 JsEventCallback<void(bool)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(tmpInfo));
755 SearchModel::GetInstance()->SetOnEditChanged(std::move(callback));
756 }
757
SetTextIndent(const JSCallbackInfo & info)758 void JSSearch::SetTextIndent(const JSCallbackInfo& info)
759 {
760 CalcDimension value;
761 RefPtr<ResourceObject> resourceObject;
762 UnregisterResource("textIndent");
763 if (!ParseJsDimensionVpNG(info[0], value, resourceObject, true)) {
764 value.Reset();
765 }
766 if (SystemProperties::ConfigChangePerform() && resourceObject) {
767 RegisterResource<CalcDimension>("textIndent", resourceObject, value);
768 }
769 SearchModel::GetInstance()->SetTextIndent(value);
770 }
771
SetPlaceholderColor(const JSCallbackInfo & info)772 void JSSearch::SetPlaceholderColor(const JSCallbackInfo& info)
773 {
774 auto value = JSRef<JSVal>::Cast(info[0]);
775 Color colorVal;
776 RefPtr<ResourceObject> resourceObject;
777 UnregisterResource("placeholderColor");
778 if (!ParseJsColor(value, colorVal, resourceObject)) {
779 SearchModel::GetInstance()->ResetPlaceholderColor();
780 return;
781 }
782 if (SystemProperties::ConfigChangePerform() && resourceObject) {
783 RegisterResource<Color>("placeholderColor", resourceObject, colorVal);
784 }
785 SearchModel::GetInstance()->SetPlaceholderColor(colorVal);
786 }
787
SetPlaceholderFont(const JSCallbackInfo & info)788 void JSSearch::SetPlaceholderFont(const JSCallbackInfo& info)
789 {
790 if (!info[0]->IsObject()) {
791 return;
792 }
793 auto param = JSRef<JSObject>::Cast(info[0]);
794 auto theme = GetTheme<SearchTheme>();
795 CHECK_NULL_VOID(theme);
796 auto themeFontSize = theme->GetFontSize();
797 Font font;
798 auto fontSize = param->GetProperty("size");
799 RefPtr<ResourceObject> resourceObject;
800 UnregisterResource("placeholderFontSize");
801 if (fontSize->IsNull() || fontSize->IsUndefined()) {
802 font.fontSize = themeFontSize;
803 } else {
804 auto versionTenOrLarger = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN);
805 CalcDimension size;
806 if ((versionTenOrLarger ?
807 ParseJsDimensionVpNG(fontSize, size, resourceObject) :
808 ParseJsDimensionVp(fontSize, size, resourceObject)) &&
809 size.Unit() != DimensionUnit::PERCENT) {
810 ParseJsDimensionFp(fontSize, size, resourceObject);
811 font.fontSize = size;
812 } else {
813 font.fontSize = themeFontSize;
814 }
815 if (SystemProperties::ConfigChangePerform() && resourceObject) {
816 RegisterResource<CalcDimension>("placeholderFontSize", resourceObject, size);
817 }
818 }
819
820 auto weight = param->GetProperty("weight");
821 if (!weight->IsNull()) {
822 std::string weightVal;
823 if (weight->IsNumber()) {
824 weightVal = std::to_string(weight->ToNumber<int32_t>());
825 } else {
826 ParseJsString(weight, weightVal);
827 }
828 font.fontWeight = ConvertStrToFontWeight(weightVal);
829 }
830
831 auto family = param->GetProperty("family");
832 if (!family->IsNull() && family->IsString()) {
833 auto familyVal = family->ToString();
834 font.fontFamilies = ConvertStrToFontFamilies(familyVal);
835 }
836
837 auto style = param->GetProperty("style");
838 if (!style->IsNull() && style->IsNumber()) {
839 FontStyle styleVal = static_cast<FontStyle>(style->ToNumber<int32_t>());
840 font.fontStyle = styleVal;
841 }
842 SearchModel::GetInstance()->SetPlaceholderFont(font);
843 }
844
SetTextFont(const JSCallbackInfo & info)845 void JSSearch::SetTextFont(const JSCallbackInfo& info)
846 {
847 auto theme = GetTheme<SearchTheme>();
848 CHECK_NULL_VOID(theme);
849 auto themeFontSize = theme->GetFontSize();
850 auto themeFontWeight = theme->GetFontWeight();
851 Font font { .fontWeight = themeFontWeight, .fontSize = themeFontSize, .fontStyle = Ace::FontStyle::NORMAL };
852 if (info.Length() < 1 || !info[0]->IsObject()) {
853 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
854 SearchModel::GetInstance()->SetTextFont(font);
855 }
856 return;
857 }
858 auto param = JSRef<JSObject>::Cast(info[0]);
859 auto fontSize = param->GetProperty("size");
860 CalcDimension size = themeFontSize;
861 RefPtr<ResourceObject> resourceObject;
862 UnregisterResource("fontSize");
863 if (ParseJsDimensionVpNG(fontSize, size, resourceObject) && size.Unit() != DimensionUnit::PERCENT &&
864 GreatOrEqual(size.Value(), 0.0)) {
865 ParseJsDimensionFp(fontSize, size, resourceObject);
866 } else {
867 size = themeFontSize;
868 }
869 font.fontSize = size;
870 if (SystemProperties::ConfigChangePerform() && resourceObject) {
871 RegisterResource<CalcDimension>("fontSize", resourceObject, size);
872 }
873
874 auto weight = param->GetProperty("weight");
875 if (!weight->IsNull()) {
876 std::string weightVal;
877 if (weight->IsNumber()) {
878 weightVal = std::to_string(weight->ToNumber<int32_t>());
879 } else {
880 ParseJsString(weight, weightVal);
881 }
882 font.fontWeight = ConvertStrToFontWeight(weightVal);
883 }
884
885 auto family = param->GetProperty("family");
886 if (!family->IsNull() && family->IsString()) {
887 auto familyVal = family->ToString();
888 font.fontFamilies = ConvertStrToFontFamilies(familyVal);
889 }
890
891 auto style = param->GetProperty("style");
892 if (!style->IsNull() && style->IsNumber()) {
893 FontStyle styleVal = static_cast<FontStyle>(style->ToNumber<int32_t>());
894 font.fontStyle = styleVal;
895 }
896 SearchModel::GetInstance()->SetTextFont(font);
897 }
898
SetTextAlign(int32_t value)899 void JSSearch::SetTextAlign(int32_t value)
900 {
901 if (value >= 0 && value < static_cast<int32_t>(TEXT_ALIGNS.size())) {
902 SearchModel::GetInstance()->SetTextAlign(TEXT_ALIGNS[value]);
903 }
904 }
905
JsBorder(const JSCallbackInfo & info)906 void JSSearch::JsBorder(const JSCallbackInfo& info)
907 {
908 if (!info[0]->IsObject()) {
909 CalcDimension borderWidth;
910 ViewAbstractModel::GetInstance()->SetBorderWidth(borderWidth);
911 ViewAbstractModel::GetInstance()->SetBorderColor(Color::BLACK);
912 ViewAbstractModel::GetInstance()->SetBorderRadius(borderWidth);
913 ViewAbstractModel::GetInstance()->SetBorderStyle(BorderStyle::SOLID);
914 ViewAbstractModel::GetInstance()->SetDashGap(Dimension(-1));
915 ViewAbstractModel::GetInstance()->SetDashWidth(Dimension(-1));
916 return;
917 }
918 JSRef<JSObject> object = JSRef<JSObject>::Cast(info[0]);
919
920 auto valueWidth = object->GetProperty(static_cast<int32_t>(ArkUIIndex::WIDTH));
921 if (!valueWidth->IsUndefined()) {
922 JSViewAbstract::ParseBorderWidth(valueWidth);
923 }
924
925 // use default value when undefined.
926 JSViewAbstract::ParseBorderColor(object->GetProperty(static_cast<int32_t>(ArkUIIndex::COLOR)));
927
928 auto valueRadius = object->GetProperty(static_cast<int32_t>(ArkUIIndex::RADIUS));
929 if (!valueRadius->IsUndefined()) {
930 JSViewAbstract::ParseBorderRadius(valueRadius);
931 SearchModel::GetInstance()->SetBackBorderRadius();
932 }
933 // use default value when undefined.
934 JSViewAbstract::ParseBorderStyle(object->GetProperty(static_cast<int32_t>(ArkUIIndex::STYLE)));
935
936 auto dashGap = object->GetProperty("dashGap");
937 if (!dashGap->IsUndefined()) {
938 JSViewAbstract::ParseDashGap(dashGap);
939 }
940 auto dashWidth = object->GetProperty("dashWidth");
941 if (!dashWidth->IsUndefined()) {
942 JSViewAbstract::ParseDashWidth(dashWidth);
943 }
944
945 SearchModel::GetInstance()->SetBackBorder();
946 info.ReturnSelf();
947 }
948
JsBorderWidth(const JSCallbackInfo & info)949 void JSSearch::JsBorderWidth(const JSCallbackInfo& info)
950 {
951 JSViewAbstract::JsBorderWidth(info);
952 if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
953 return;
954 }
955 SearchModel::GetInstance()->SetBackBorder();
956 }
957
JsBorderColor(const JSCallbackInfo & info)958 void JSSearch::JsBorderColor(const JSCallbackInfo& info)
959 {
960 JSViewAbstract::JsBorderColor(info);
961 if (!info[0]->IsObject() && !info[0]->IsString() && !info[0]->IsNumber()) {
962 return;
963 }
964 SearchModel::GetInstance()->SetBackBorder();
965 }
966
JsBorderStyle(const JSCallbackInfo & info)967 void JSSearch::JsBorderStyle(const JSCallbackInfo& info)
968 {
969 JSViewAbstract::JsBorderStyle(info);
970 if (!info[0]->IsObject() && !info[0]->IsNumber()) {
971 return;
972 }
973 SearchModel::GetInstance()->SetBackBorder();
974 }
975
GetBorderRadiusByLengthMetrics(const char * key,JSRef<JSObject> & object,std::optional<CalcDimension> & radius)976 void JSSearch::GetBorderRadiusByLengthMetrics(const char* key, JSRef<JSObject>& object,
977 std::optional<CalcDimension>& radius)
978 {
979 if (object->HasProperty(key) && object->GetProperty(key)->IsObject()) {
980 JSRef<JSObject> startObj = JSRef<JSObject>::Cast(object->GetProperty(key));
981 CalcDimension value;
982 ParseJsLengthMetrics(startObj, value);
983 radius = value;
984 }
985 }
986
ParseAllBorderRadiuses(JSRef<JSObject> & object,CalcDimension & topLeft,CalcDimension & topRight,CalcDimension & bottomLeft,CalcDimension & bottomRight)987 bool JSSearch::ParseAllBorderRadiuses(JSRef<JSObject>& object, CalcDimension& topLeft,
988 CalcDimension& topRight, CalcDimension& bottomLeft, CalcDimension& bottomRight)
989 {
990 if (object->HasProperty(TOP_START_PROPERTY) || object->HasProperty(TOP_END_PROPERTY) ||
991 object->HasProperty(BOTTOM_START_PROPERTY) || object->HasProperty(BOTTOM_END_PROPERTY)) {
992 std::optional<CalcDimension> topStart;
993 std::optional<CalcDimension> topEnd;
994 std::optional<CalcDimension> bottomStart;
995 std::optional<CalcDimension> bottomEnd;
996 GetBorderRadiusByLengthMetrics(TOP_START_PROPERTY, object, topStart);
997 GetBorderRadiusByLengthMetrics(TOP_END_PROPERTY, object, topEnd);
998 GetBorderRadiusByLengthMetrics(BOTTOM_START_PROPERTY, object, bottomStart);
999 GetBorderRadiusByLengthMetrics(BOTTOM_END_PROPERTY, object, bottomEnd);
1000 topLeft = topStart.has_value() ? topStart.value() : topLeft;
1001 topRight = topEnd.has_value() ? topEnd.value() : topRight;
1002 bottomLeft = bottomStart.has_value() ? bottomStart.value() : bottomLeft;
1003 bottomRight = bottomEnd.has_value() ? bottomEnd.value() : bottomRight;
1004 return true;
1005 }
1006 JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topLeft"), topLeft);
1007 JSViewAbstract::ParseJsDimensionVp(object->GetProperty("topRight"), topRight);
1008 JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomLeft"), bottomLeft);
1009 JSViewAbstract::ParseJsDimensionVp(object->GetProperty("bottomRight"), bottomRight);
1010 return false;
1011 }
1012
ParseBorderRadius(const JSRef<JSVal> & args)1013 void JSSearch::ParseBorderRadius(const JSRef<JSVal>& args)
1014 {
1015 CalcDimension borderRadius;
1016 if (ParseJsDimensionVp(args, borderRadius)) {
1017 ViewAbstractModel::GetInstance()->SetBorderRadius(borderRadius);
1018 } else if (args->IsObject()) {
1019 auto textFieldTheme = GetTheme<TextFieldTheme>();
1020 CHECK_NULL_VOID(textFieldTheme);
1021 auto borderRadiusTheme = textFieldTheme->GetBorderRadius();
1022 NG::BorderRadiusProperty defaultBorderRadius {
1023 borderRadiusTheme.GetX(), borderRadiusTheme.GetY(),
1024 borderRadiusTheme.GetY(), borderRadiusTheme.GetX(),
1025 };
1026
1027 JSRef<JSObject> object = JSRef<JSObject>::Cast(args);
1028 CalcDimension topLeft = defaultBorderRadius.radiusTopLeft.value();
1029 CalcDimension topRight = defaultBorderRadius.radiusTopRight.value();
1030 CalcDimension bottomLeft = defaultBorderRadius.radiusBottomLeft.value();
1031 CalcDimension bottomRight = defaultBorderRadius.radiusBottomRight.value();
1032 if (ParseAllBorderRadiuses(object, topLeft, topRight, bottomLeft, bottomRight)) {
1033 ViewAbstractModel::GetInstance()->SetBorderRadius(
1034 JSViewAbstract::GetLocalizedBorderRadius(topLeft, topRight, bottomLeft, bottomRight));
1035 return;
1036 }
1037 ViewAbstractModel::GetInstance()->SetBorderRadius(topLeft, topRight, bottomLeft, bottomRight);
1038 }
1039 }
1040
JsBorderRadius(const JSCallbackInfo & info)1041 void JSSearch::JsBorderRadius(const JSCallbackInfo& info)
1042 {
1043 auto jsValue = info[0];
1044 static std::vector<JSCallbackInfoType> checkList { JSCallbackInfoType::STRING,
1045 JSCallbackInfoType::NUMBER, JSCallbackInfoType::OBJECT };
1046 if (!CheckJSCallbackInfo("JsBorderRadius", jsValue, checkList)) {
1047 auto textFieldTheme = GetTheme<TextFieldTheme>();
1048 CHECK_NULL_VOID(textFieldTheme);
1049 auto borderRadiusTheme = textFieldTheme->GetBorderRadius();
1050 NG::BorderRadiusProperty defaultBorderRadius {
1051 borderRadiusTheme.GetX(), borderRadiusTheme.GetY(),
1052 borderRadiusTheme.GetY(), borderRadiusTheme.GetX(),
1053 };
1054 ViewAbstractModel::GetInstance()->SetBorderRadius(defaultBorderRadius);
1055 return;
1056 }
1057 ParseBorderRadius(jsValue);
1058 SearchModel::GetInstance()->SetBackBorderRadius();
1059 }
1060
CreateJsSearchCommonEvent(const JSCallbackInfo & info)1061 void JSSearch::CreateJsSearchCommonEvent(const JSCallbackInfo &info)
1062 {
1063 if (info.Length() < 1 || !info[0]->IsFunction()) {
1064 return;
1065 }
1066 auto jsTextFunc = AceType::MakeRefPtr<JsCommonEventFunction<NG::TextFieldCommonEvent, 2>>(
1067 JSRef<JSFunc>::Cast(info[0]));
1068 WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
1069 auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc), node = targetNode](
1070 const std::u16string& value, NG::TextFieldCommonEvent& event) {
1071 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1072 ACE_SCORING_EVENT("onSubmit");
1073 PipelineContext::SetCallBackNode(node);
1074 JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1075 objectTemplate->SetInternalFieldCount(2);
1076 JSRef<JSObject> object = objectTemplate->NewInstance();
1077 object->SetProperty<std::u16string>("text", event.GetText());
1078 object->SetPropertyObject(
1079 "keepEditableState", JSRef<JSFunc>::New<FunctionCallback>(JSTextField::JsKeepEditableState));
1080 object->Wrap<NG::TextFieldCommonEvent>(&event);
1081 JSRef<JSVal> stringValue = JSRef<JSVal>::Make(ToJSValue(value));
1082 JSRef<JSVal> dataObject = JSRef<JSVal>::Cast(object);
1083 JSRef<JSVal> param[2] = {stringValue, dataObject};
1084 func->Execute(param);
1085 UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", "onSubmit");
1086 };
1087 SearchModel::GetInstance()->SetOnSubmit(std::move(callback));
1088 }
1089
OnSubmit(const JSCallbackInfo & info)1090 void JSSearch::OnSubmit(const JSCallbackInfo& info)
1091 {
1092 auto jsValue = info[0];
1093 CHECK_NULL_VOID(jsValue->IsFunction());
1094 #ifdef NG_BUILD
1095 CreateJsSearchCommonEvent(info);
1096 #else
1097 if (Container::IsCurrentUseNewPipeline()) {
1098 CreateJsSearchCommonEvent(info);
1099 } else {
1100 JsEventCallback<void(const std::string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(jsValue));
1101 SearchModel::GetInstance()->SetOnSubmit(std::move(callback));
1102 }
1103 #endif
1104 }
1105
CreateJsOnChangeObj(const PreviewText & previewText)1106 JSRef<JSVal> JSSearch::CreateJsOnChangeObj(const PreviewText& previewText)
1107 {
1108 JSRef<JSObject> previewTextObj = JSRef<JSObject>::New();
1109 previewTextObj->SetProperty<int32_t>("offset", previewText.offset);
1110 previewTextObj->SetProperty<std::u16string>("value", previewText.value);
1111 return JSRef<JSVal>::Cast(previewTextObj);
1112 }
1113
OnChange(const JSCallbackInfo & info)1114 void JSSearch::OnChange(const JSCallbackInfo& info)
1115 {
1116 auto jsValue = info[0];
1117 CHECK_NULL_VOID(jsValue->IsFunction());
1118 auto jsChangeFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(jsValue));
1119 auto onChange = [execCtx = info.GetExecutionContext(), func = std::move(jsChangeFunc)](
1120 const ChangeValueInfo& changeValueInfo) {
1121 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1122 ACE_SCORING_EVENT("onChange");
1123 JSRef<JSVal> valueObj = JSRef<JSVal>::Make(ToJSValue(changeValueInfo.value));
1124 auto previewTextObj = CreateJsOnChangeObj(changeValueInfo.previewText);
1125 auto optionsObj = JSRef<JSObject>::New();
1126 auto rangeBeforeObj = JSRef<JSObject>::New();
1127 rangeBeforeObj->SetProperty<int32_t>("start", changeValueInfo.rangeBefore.start);
1128 rangeBeforeObj->SetProperty<int32_t>("end", changeValueInfo.rangeBefore.end);
1129 optionsObj->SetPropertyObject("rangeBefore", rangeBeforeObj);
1130 auto rangeAfterObj = JSRef<JSObject>::New();
1131 rangeAfterObj->SetProperty<int32_t>("start", changeValueInfo.rangeAfter.start);
1132 rangeAfterObj->SetProperty<int32_t>("end", changeValueInfo.rangeAfter.end);
1133 optionsObj->SetPropertyObject("rangeAfter", rangeAfterObj);
1134 optionsObj->SetProperty<std::u16string>("oldContent", changeValueInfo.oldContent);
1135 auto oldPreviewTextObj = CreateJsOnChangeObj(changeValueInfo.oldPreviewText);
1136 optionsObj->SetPropertyObject("oldPreviewText", oldPreviewTextObj);
1137 JSRef<JSVal> argv[] = { valueObj, previewTextObj, optionsObj };
1138 func->ExecuteJS(3, argv);
1139 };
1140 SearchModel::GetInstance()->SetOnChange(std::move(onChange));
1141 }
1142
SetOnTextSelectionChange(const JSCallbackInfo & info)1143 void JSSearch::SetOnTextSelectionChange(const JSCallbackInfo& info)
1144 {
1145 CHECK_NULL_VOID(info[0]->IsFunction());
1146 JsEventCallback<void(int32_t, int32_t)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
1147 SearchModel::GetInstance()->SetOnTextSelectionChange(std::move(callback));
1148 }
1149
SetOnScroll(const JSCallbackInfo & info)1150 void JSSearch::SetOnScroll(const JSCallbackInfo& info)
1151 {
1152 CHECK_NULL_VOID(info[0]->IsFunction());
1153 JsEventCallback<void(float, float)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
1154 SearchModel::GetInstance()->SetOnScroll(std::move(callback));
1155 }
1156
SetHeight(const JSCallbackInfo & info)1157 void JSSearch::SetHeight(const JSCallbackInfo& info)
1158 {
1159 JSViewAbstract::JsHeight(info);
1160 CalcDimension value;
1161 auto versionTenOrLarger = Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_TEN);
1162 if (versionTenOrLarger ? !ParseJsDimensionVpNG(info[0], value) : !ParseJsDimensionVp(info[0], value)) {
1163 return;
1164 }
1165 if (LessNotEqual(value.Value(), 0.0)) {
1166 value.SetValue(0.0);
1167 }
1168 SearchModel::GetInstance()->SetHeight(value);
1169 }
1170
SetOnCopy(const JSCallbackInfo & info)1171 void JSSearch::SetOnCopy(const JSCallbackInfo& info)
1172 {
1173 CHECK_NULL_VOID(info[0]->IsFunction());
1174 JsEventCallback<void(const std::u16string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
1175 SearchModel::GetInstance()->SetOnCopy(std::move(callback));
1176 }
1177
SetOnCut(const JSCallbackInfo & info)1178 void JSSearch::SetOnCut(const JSCallbackInfo& info)
1179 {
1180 CHECK_NULL_VOID(info[0]->IsFunction());
1181 JsEventCallback<void(const std::u16string&)> callback(info.GetExecutionContext(), JSRef<JSFunc>::Cast(info[0]));
1182 SearchModel::GetInstance()->SetOnCut(std::move(callback));
1183 }
1184
CreateJSTextCommonEvent(NG::TextCommonEvent & event)1185 JSRef<JSVal> JSSearch::CreateJSTextCommonEvent(NG::TextCommonEvent& event)
1186 {
1187 JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
1188 objectTemplate->SetInternalFieldCount(1);
1189 JSRef<JSObject> object = objectTemplate->NewInstance();
1190 object->SetPropertyObject("preventDefault", JSRef<JSFunc>::New<FunctionCallback>(JsPreventDefault));
1191 object->Wrap<NG::TextCommonEvent>(&event);
1192 return JSRef<JSVal>::Cast(object);
1193 }
1194
SetOnPaste(const JSCallbackInfo & info)1195 void JSSearch::SetOnPaste(const JSCallbackInfo& info)
1196 {
1197 CHECK_NULL_VOID(info[0]->IsFunction());
1198 auto jsTextFunc = AceType::MakeRefPtr<JsCitedEventFunction<NG::TextCommonEvent, 2>>(
1199 JSRef<JSFunc>::Cast(info[0]), CreateJSTextCommonEvent);
1200
1201 auto onPaste = [execCtx = info.GetExecutionContext(), func = std::move(jsTextFunc)](
1202 const std::u16string& val, NG::TextCommonEvent& info) {
1203 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1204 ACE_SCORING_EVENT("onPaste");
1205 func->Execute(val, info);
1206 UiSessionManager::GetInstance()->ReportComponentChangeEvent("event", "onPaste");
1207 };
1208 SearchModel::GetInstance()->SetOnPasteWithEvent(std::move(onPaste));
1209 }
1210
SetCopyOption(const JSCallbackInfo & info)1211 void JSSearch::SetCopyOption(const JSCallbackInfo& info)
1212 {
1213 if (info.Length() == 0) {
1214 return;
1215 }
1216 if (info[0]->IsUndefined()) {
1217 SearchModel::GetInstance()->SetCopyOption(CopyOptions::Local);
1218 return;
1219 }
1220 auto copyOptions = CopyOptions::Local;
1221 if (info[0]->IsNumber()) {
1222 auto emunNumber = info[0]->ToNumber<int>();
1223 copyOptions = static_cast<CopyOptions>(emunNumber);
1224 }
1225 SearchModel::GetInstance()->SetCopyOption(copyOptions);
1226 }
1227
CreateJsAboutToIMEInputObj(const InsertValueInfo & insertValue)1228 JSRef<JSVal> JSSearch::CreateJsAboutToIMEInputObj(const InsertValueInfo& insertValue)
1229 {
1230 JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1231 aboutToIMEInputObj->SetProperty<int32_t>("insertOffset", insertValue.insertOffset);
1232 aboutToIMEInputObj->SetProperty<std::u16string>("insertValue", insertValue.insertValue);
1233 return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1234 }
1235
OnWillInsertValue(const JSCallbackInfo & info)1236 void JSSearch::OnWillInsertValue(const JSCallbackInfo& info)
1237 {
1238 auto jsValue = info[0];
1239 CHECK_NULL_VOID(jsValue->IsFunction());
1240 auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1241 JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1242 auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1243 const InsertValueInfo& insertValue) -> bool {
1244 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1245 auto ret = func->ExecuteWithValue(insertValue);
1246 if (ret->IsBoolean()) {
1247 return ret->ToBoolean();
1248 }
1249 return true;
1250 };
1251 SearchModel::GetInstance()->SetOnWillInsertValueEvent(std::move(callback));
1252 }
1253
CreateJsDeleteToIMEObj(const DeleteValueInfo & deleteValueInfo)1254 JSRef<JSVal> JSSearch::CreateJsDeleteToIMEObj(const DeleteValueInfo& deleteValueInfo)
1255 {
1256 JSRef<JSObject> aboutToIMEInputObj = JSRef<JSObject>::New();
1257 aboutToIMEInputObj->SetProperty<int32_t>("deleteOffset", deleteValueInfo.deleteOffset);
1258 aboutToIMEInputObj->SetProperty<int32_t>("direction", static_cast<int32_t>(deleteValueInfo.direction));
1259 aboutToIMEInputObj->SetProperty<std::u16string>("deleteValue", deleteValueInfo.deleteValue);
1260 return JSRef<JSVal>::Cast(aboutToIMEInputObj);
1261 }
1262
OnDidInsertValue(const JSCallbackInfo & info)1263 void JSSearch::OnDidInsertValue(const JSCallbackInfo& info)
1264 {
1265 auto jsValue = info[0];
1266 CHECK_NULL_VOID(jsValue->IsFunction());
1267 auto jsAboutToIMEInputFunc = AceType::MakeRefPtr<JsEventFunction<InsertValueInfo, 1>>(
1268 JSRef<JSFunc>::Cast(jsValue), CreateJsAboutToIMEInputObj);
1269 auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1270 const InsertValueInfo& insertValue) {
1271 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1272 func->ExecuteWithValue(insertValue);
1273 };
1274 SearchModel::GetInstance()->SetOnDidInsertValueEvent(std::move(callback));
1275 }
1276
OnWillDelete(const JSCallbackInfo & info)1277 void JSSearch::OnWillDelete(const JSCallbackInfo& info)
1278 {
1279 auto jsValue = info[0];
1280 CHECK_NULL_VOID(jsValue->IsFunction());
1281 auto jsAboutToIMEInputFunc =
1282 AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1283 auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1284 const DeleteValueInfo& deleteValue) {
1285 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1286 auto ret = func->ExecuteWithValue(deleteValue);
1287 if (ret->IsBoolean()) {
1288 return ret->ToBoolean();
1289 }
1290 return true;
1291 };
1292 SearchModel::GetInstance()->SetOnWillDeleteEvent(std::move(callback));
1293 }
1294
OnDidDelete(const JSCallbackInfo & info)1295 void JSSearch::OnDidDelete(const JSCallbackInfo& info)
1296 {
1297 auto jsValue = info[0];
1298 CHECK_NULL_VOID(jsValue->IsFunction());
1299 auto jsAboutToIMEInputFunc =
1300 AceType::MakeRefPtr<JsEventFunction<DeleteValueInfo, 1>>(JSRef<JSFunc>::Cast(jsValue), CreateJsDeleteToIMEObj);
1301 auto callback = [execCtx = info.GetExecutionContext(), func = std::move(jsAboutToIMEInputFunc)](
1302 const DeleteValueInfo& deleteValue) {
1303 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1304 func->ExecuteWithValue(deleteValue);
1305 };
1306 SearchModel::GetInstance()->SetOnDidDeleteEvent(std::move(callback));
1307 }
1308
SetSelectionMenuHidden(const JSCallbackInfo & info)1309 void JSSearch::SetSelectionMenuHidden(const JSCallbackInfo& info)
1310 {
1311 if (info[0]->IsUndefined() || !info[0]->IsBoolean()) {
1312 SearchModel::GetInstance()->SetSelectionMenuHidden(false);
1313 return;
1314 }
1315 SearchModel::GetInstance()->SetSelectionMenuHidden(info[0]->ToBoolean());
1316 }
1317
SetCustomKeyboard(const JSCallbackInfo & info)1318 void JSSearch::SetCustomKeyboard(const JSCallbackInfo& info)
1319 {
1320 if (info.Length() > 0 && (info[0]->IsUndefined() || info[0]->IsNull())) {
1321 SearchModel::GetInstance()->SetCustomKeyboard(nullptr);
1322 return;
1323 }
1324 if (info.Length() < 1 || !info[0]->IsObject()) {
1325 return;
1326 }
1327 bool supportAvoidance = false;
1328 if (info.Length() == 2 && info[1]->IsObject()) { // 2 here refers to the number of parameters
1329 auto paramObject = JSRef<JSObject>::Cast(info[1]);
1330 auto isSupportAvoidance = paramObject->GetProperty("supportAvoidance");
1331 if (!isSupportAvoidance->IsNull() && isSupportAvoidance->IsBoolean()) {
1332 supportAvoidance = isSupportAvoidance->ToBoolean();
1333 }
1334 }
1335 std::function<void()> buildFunc;
1336 if (JSTextField::ParseJsCustomKeyboardBuilder(info, 0, buildFunc)) {
1337 SearchModel::GetInstance()->SetCustomKeyboard(std::move(buildFunc), supportAvoidance);
1338 }
1339 }
1340
SetType(const JSCallbackInfo & info)1341 void JSSearch::SetType(const JSCallbackInfo& info)
1342 {
1343 if (info.Length() < 1) {
1344 return;
1345 }
1346 if (info[0]->IsUndefined()) {
1347 SearchModel::GetInstance()->SetType(TextInputType::UNSPECIFIED);
1348 return;
1349 }
1350 if (!info[0]->IsNumber()) {
1351 return;
1352 }
1353 TextInputType textInputType = CastToTextInputType(info[0]->ToNumber<int32_t>());
1354 SearchModel::GetInstance()->SetType(textInputType);
1355 }
1356
JSBind(BindingTarget globalObj)1357 void JSSearchController::JSBind(BindingTarget globalObj)
1358 {
1359 JSClass<JSTextEditableController>::Declare("SearchController");
1360 JSTextEditableController::JSBind(globalObj);
1361 }
1362
SetEnterKeyType(const JSCallbackInfo & info)1363 void JSSearch::SetEnterKeyType(const JSCallbackInfo& info)
1364 {
1365 if (info.Length() < 1) {
1366 return;
1367 }
1368 if (info[0]->IsUndefined()) {
1369 SearchModel::GetInstance()->SetSearchEnterKeyType(TextInputAction::SEARCH);
1370 return;
1371 }
1372 if (!info[0]->IsNumber()) {
1373 return;
1374 }
1375 TextInputAction textInputAction = CastToTextInputAction(info[0]->ToNumber<int32_t>());
1376 SearchModel::GetInstance()->SetSearchEnterKeyType(textInputAction);
1377 }
1378
SetCapitalizationMode(const JSCallbackInfo & info)1379 void JSSearch::SetCapitalizationMode(const JSCallbackInfo& info)
1380 {
1381 if (info.Length() < 1) {
1382 return;
1383 }
1384 auto jsValue = info[0];
1385 auto autoCapitalizationMode = AutoCapitalizationMode::NONE;
1386 if (jsValue->IsUndefined() || !jsValue->IsNumber() || jsValue->IsNull()) {
1387 SearchModel::GetInstance()->SetSearchCapitalizationMode(autoCapitalizationMode);
1388 return;
1389 }
1390 if (jsValue->IsNumber()) {
1391 auto emunNumber = jsValue->ToNumber<int32_t>();
1392 autoCapitalizationMode = CastToAutoCapitalizationMode(emunNumber);
1393 }
1394 SearchModel::GetInstance()->SetSearchCapitalizationMode(autoCapitalizationMode);
1395 }
1396
SetMaxLength(const JSCallbackInfo & info)1397 void JSSearch::SetMaxLength(const JSCallbackInfo& info)
1398 {
1399 int32_t maxLength = 0;
1400 if (info[0]->IsUndefined()) {
1401 SearchModel::GetInstance()->ResetMaxLength();
1402 return;
1403 } else if (!info[0]->IsNumber()) {
1404 SearchModel::GetInstance()->ResetMaxLength();
1405 return;
1406 }
1407 maxLength = info[0]->ToNumber<int32_t>();
1408 if (std::isinf(info[0]->ToNumber<float>())) {
1409 maxLength = INT32_MAX; // Infinity
1410 }
1411 if (GreatOrEqual(maxLength, 0)) {
1412 SearchModel::GetInstance()->SetMaxLength(maxLength);
1413 } else {
1414 SearchModel::GetInstance()->ResetMaxLength();
1415 }
1416 }
1417
SetDecoration(const JSCallbackInfo & info)1418 void JSSearch::SetDecoration(const JSCallbackInfo& info)
1419 {
1420 auto tmpInfo = info[0];
1421 UnregisterResource("decorationColor");
1422 if (!tmpInfo->IsObject()) {
1423 SearchModel::GetInstance()->SetTextDecoration(TextDecoration::NONE);
1424 SearchModel::GetInstance()->SetTextDecorationColor(Color::BLACK);
1425 SearchModel::GetInstance()->SetTextDecorationStyle(TextDecorationStyle::SOLID);
1426 return;
1427 }
1428 JSRef<JSObject> obj = JSRef<JSObject>::Cast(tmpInfo);
1429 JSRef<JSVal> typeValue = obj->GetProperty("type");
1430 JSRef<JSVal> colorValue = obj->GetProperty("color");
1431 JSRef<JSVal> styleValue = obj->GetProperty("style");
1432
1433 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
1434 CHECK_NULL_VOID(pipelineContext);
1435 auto theme = pipelineContext->GetTheme<SearchTheme>();
1436 CHECK_NULL_VOID(theme);
1437 TextDecoration textDecoration = theme->GetTextDecoration();
1438 if (typeValue->IsNumber()) {
1439 textDecoration = static_cast<TextDecoration>(typeValue->ToNumber<int32_t>());
1440 }
1441 Color result = theme->GetTextStyle().GetTextDecorationColor();
1442 RefPtr<ResourceObject> resourceObject;
1443 ParseJsColor(colorValue, result, Color::BLACK, resourceObject);
1444 if (SystemProperties::ConfigChangePerform() && resourceObject) {
1445 RegisterResource<Color>("decorationColor", resourceObject, result);
1446 }
1447 std::optional<TextDecorationStyle> textDecorationStyle;
1448 if (styleValue->IsNumber()) {
1449 textDecorationStyle = static_cast<TextDecorationStyle>(styleValue->ToNumber<int32_t>());
1450 } else {
1451 textDecorationStyle = DEFAULT_TEXT_DECORATION_STYLE;
1452 }
1453 SearchModel::GetInstance()->SetTextDecoration(textDecoration);
1454 SearchModel::GetInstance()->SetTextDecorationColor(result);
1455 if (textDecorationStyle) {
1456 SearchModel::GetInstance()->SetTextDecorationStyle(textDecorationStyle.value());
1457 }
1458 }
1459
SetMinFontSize(const JSCallbackInfo & info)1460 void JSSearch::SetMinFontSize(const JSCallbackInfo& info)
1461 {
1462 if (info.Length() < 1) {
1463 return;
1464 }
1465 CalcDimension minFontSize;
1466 RefPtr<ResourceObject> resourceObject;
1467 UnregisterResource("minFontSize");
1468 if (!ParseJsDimensionFpNG(info[0], minFontSize, resourceObject, false)) {
1469 SearchModel::GetInstance()->SetAdaptMinFontSize(CalcDimension());
1470 return;
1471 }
1472 if (SystemProperties::ConfigChangePerform() && resourceObject) {
1473 RegisterResource<CalcDimension>("minFontSize", resourceObject, minFontSize);
1474 }
1475 if (minFontSize.IsNegative()) {
1476 minFontSize = CalcDimension();
1477 }
1478 SearchModel::GetInstance()->SetAdaptMinFontSize(minFontSize);
1479 }
1480
SetMaxFontSize(const JSCallbackInfo & info)1481 void JSSearch::SetMaxFontSize(const JSCallbackInfo& info)
1482 {
1483 if (info.Length() < 1) {
1484 return;
1485 }
1486 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
1487 CHECK_NULL_VOID(pipelineContext);
1488 auto theme = pipelineContext->GetTheme<SearchTheme>();
1489 CHECK_NULL_VOID(theme);
1490 CalcDimension maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1491
1492 RefPtr<ResourceObject> resourceObject;
1493 UnregisterResource("maxFontSize");
1494 if (!ParseJsDimensionFpNG(info[0], maxFontSize, resourceObject, false)) {
1495 maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1496 SearchModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1497 return;
1498 }
1499 if (SystemProperties::ConfigChangePerform() && resourceObject) {
1500 RegisterResource<CalcDimension>("maxFontSize", resourceObject, maxFontSize);
1501 }
1502 if (maxFontSize.IsNegative()) {
1503 maxFontSize = theme->GetTextStyle().GetAdaptMaxFontSize();
1504 }
1505 SearchModel::GetInstance()->SetAdaptMaxFontSize(maxFontSize);
1506 }
1507
SetMinFontScale(const JSCallbackInfo & info)1508 void JSSearch::SetMinFontScale(const JSCallbackInfo& info)
1509 {
1510 double minFontScale = 0.0;
1511 RefPtr<ResourceObject> resourceObject;
1512 if (info.Length() < 1 || !ParseJsDouble(info[0], minFontScale, resourceObject)) {
1513 return;
1514 }
1515 if (SystemProperties::ConfigChangePerform() && resourceObject) {
1516 RegisterResource<float>("minFontScale", resourceObject, minFontScale);
1517 } else {
1518 UnregisterResource("minFontScale");
1519 }
1520 if (LessOrEqual(minFontScale, 0.0f)) {
1521 SearchModel::GetInstance()->SetMinFontScale(0.0f);
1522 return;
1523 }
1524 if (GreatOrEqual(minFontScale, 1.0f)) {
1525 SearchModel::GetInstance()->SetMinFontScale(1.0f);
1526 return;
1527 }
1528 SearchModel::GetInstance()->SetMinFontScale(static_cast<float>(minFontScale));
1529 }
1530
SetMaxFontScale(const JSCallbackInfo & info)1531 void JSSearch::SetMaxFontScale(const JSCallbackInfo& info)
1532 {
1533 double maxFontScale = 0.0;
1534 RefPtr<ResourceObject> resourceObject;
1535 if (info.Length() < 1 || !ParseJsDouble(info[0], maxFontScale, resourceObject)) {
1536 return;
1537 }
1538 if (SystemProperties::ConfigChangePerform() && resourceObject) {
1539 RegisterResource<float>("maxFontScale", resourceObject, maxFontScale);
1540 } else {
1541 UnregisterResource("maxFontScale");
1542 }
1543 if (LessOrEqual(maxFontScale, 1.0f)) {
1544 SearchModel::GetInstance()->SetMaxFontScale(1.0f);
1545 return;
1546 }
1547 SearchModel::GetInstance()->SetMaxFontScale(static_cast<float>(maxFontScale));
1548 }
1549
SetLetterSpacing(const JSCallbackInfo & info)1550 void JSSearch::SetLetterSpacing(const JSCallbackInfo& info)
1551 {
1552 CalcDimension value;
1553 RefPtr<ResourceObject> resourceObject;
1554 if (!ParseJsDimensionFpNG(info[0], value, resourceObject, false)) {
1555 value.Reset();
1556 SearchModel::GetInstance()->SetLetterSpacing(value);
1557 UnregisterResource("letterSpacing");
1558 return;
1559 }
1560 if (SystemProperties::ConfigChangePerform() && resourceObject) {
1561 RegisterResource<CalcDimension>("letterSpacing", resourceObject, value);
1562 }
1563 SearchModel::GetInstance()->SetLetterSpacing(value);
1564 }
1565
SetLineHeight(const JSCallbackInfo & info)1566 void JSSearch::SetLineHeight(const JSCallbackInfo& info)
1567 {
1568 CalcDimension value;
1569 RefPtr<ResourceObject> resourceObject;
1570 if (!ParseJsDimensionFpNG(info[0], value, resourceObject)) {
1571 value.Reset();
1572 SearchModel::GetInstance()->SetLineHeight(value);
1573 UnregisterResource("lineHeight");
1574 return;
1575 }
1576 if (SystemProperties::ConfigChangePerform() && resourceObject) {
1577 RegisterResource<CalcDimension>("lineHeight", resourceObject, value);
1578 }
1579 if (value.IsNegative()) {
1580 value.Reset();
1581 }
1582 SearchModel::GetInstance()->SetLineHeight(value);
1583 }
1584
SetHalfLeading(const JSCallbackInfo & info)1585 void JSSearch::SetHalfLeading(const JSCallbackInfo& info)
1586 {
1587 if (info.Length() < 1) {
1588 return;
1589 }
1590 auto jsValue = info[0];
1591 bool halfLeading = jsValue->IsBoolean() ? jsValue->ToBoolean() : false;
1592 SearchModel::GetInstance()->SetHalfLeading(halfLeading);
1593 }
1594
EditMenuOptions(const JSCallbackInfo & info)1595 void JSSearch::EditMenuOptions(const JSCallbackInfo& info)
1596 {
1597 NG::OnCreateMenuCallback onCreateMenuCallback;
1598 NG::OnMenuItemClickCallback onMenuItemClick;
1599 NG::OnPrepareMenuCallback onPrepareMenuCallback;
1600 JSViewAbstract::ParseEditMenuOptions(info, onCreateMenuCallback, onMenuItemClick, onPrepareMenuCallback);
1601 SearchModel::GetInstance()->SetSelectionMenuOptions(
1602 std::move(onCreateMenuCallback), std::move(onMenuItemClick), std::move(onPrepareMenuCallback));
1603 }
1604
SetEnablePreviewText(const JSCallbackInfo & info)1605 void JSSearch::SetEnablePreviewText(const JSCallbackInfo& info)
1606 {
1607 auto jsValue = info[0];
1608 if (!jsValue->IsBoolean()) {
1609 SearchModel::GetInstance()->SetEnablePreviewText(true);
1610 return;
1611 }
1612 SearchModel::GetInstance()->SetEnablePreviewText(jsValue->ToBoolean());
1613 }
1614
SetEnableHapticFeedback(const JSCallbackInfo & info)1615 void JSSearch::SetEnableHapticFeedback(const JSCallbackInfo& info)
1616 {
1617 bool state = true;
1618 if (info.Length() > 0 && info[0]->IsBoolean()) {
1619 state = info[0]->ToBoolean();
1620 }
1621 SearchModel::GetInstance()->SetEnableHapticFeedback(state);
1622 }
1623
SetStopBackPress(const JSCallbackInfo & info)1624 void JSSearch::SetStopBackPress(const JSCallbackInfo& info)
1625 {
1626 bool isStopBackPress = true;
1627 if (info.Length() > 0 && info[0]->IsBoolean()) {
1628 isStopBackPress = info[0]->ToBoolean();
1629 }
1630 SearchModel::GetInstance()->SetStopBackPress(isStopBackPress);
1631 }
1632
SetKeyboardAppearance(const JSCallbackInfo & info)1633 void JSSearch::SetKeyboardAppearance(const JSCallbackInfo& info)
1634 {
1635 if (info.Length() != 1 || !info[0]->IsNumber()) {
1636 SearchModel::GetInstance()->SetKeyboardAppearance(
1637 static_cast<KeyboardAppearance>(KeyboardAppearance::NONE_IMMERSIVE));
1638 return;
1639 }
1640 auto keyboardAppearance = info[0]->ToNumber<uint32_t>();
1641 if (keyboardAppearance < static_cast<uint32_t>(KeyboardAppearance::NONE_IMMERSIVE) ||
1642 keyboardAppearance > static_cast<uint32_t>(KeyboardAppearance::DARK_IMMERSIVE)) {
1643 SearchModel::GetInstance()->SetKeyboardAppearance(
1644 static_cast<KeyboardAppearance>(KeyboardAppearance::NONE_IMMERSIVE));
1645 return;
1646 }
1647 SearchModel::GetInstance()->SetKeyboardAppearance(
1648 static_cast<KeyboardAppearance>(keyboardAppearance));
1649 }
1650
CreateJsOnWillChangeObj(const ChangeValueInfo & changeValueInfo)1651 JSRef<JSVal> JSSearch::CreateJsOnWillChangeObj(const ChangeValueInfo& changeValueInfo)
1652 {
1653 JSRef<JSObject> ChangeValueInfo = JSRef<JSObject>::New();
1654 ChangeValueInfo->SetProperty<std::u16string>("content", changeValueInfo.value);
1655
1656 auto previewTextObj = CreateJsOnChangeObj(changeValueInfo.previewText);
1657 ChangeValueInfo->SetPropertyObject("previewText", previewTextObj);
1658
1659 auto optionsObj = JSRef<JSObject>::New();
1660 auto rangeBeforeObj = JSRef<JSObject>::New();
1661 rangeBeforeObj->SetProperty<int32_t>("start", changeValueInfo.rangeBefore.start);
1662 rangeBeforeObj->SetProperty<int32_t>("end", changeValueInfo.rangeBefore.end);
1663 optionsObj->SetPropertyObject("rangeBefore", rangeBeforeObj);
1664 auto rangeAfterObj = JSRef<JSObject>::New();
1665 rangeAfterObj->SetProperty<int32_t>("start", changeValueInfo.rangeAfter.start);
1666 rangeAfterObj->SetProperty<int32_t>("end", changeValueInfo.rangeAfter.end);
1667 optionsObj->SetPropertyObject("rangeAfter", rangeAfterObj);
1668 optionsObj->SetProperty<std::u16string>("oldContent", changeValueInfo.oldContent);
1669 auto oldPreviewTextObj = CreateJsOnChangeObj(changeValueInfo.oldPreviewText);
1670 optionsObj->SetPropertyObject("oldPreviewText", oldPreviewTextObj);
1671
1672 ChangeValueInfo->SetPropertyObject("options", optionsObj);
1673 return JSRef<JSVal>::Cast(ChangeValueInfo);
1674 }
1675
SetOnWillChange(const JSCallbackInfo & info)1676 void JSSearch::SetOnWillChange(const JSCallbackInfo& info)
1677 {
1678 auto jsValue = info[0];
1679 CHECK_NULL_VOID(jsValue->IsFunction());
1680 auto jsChangeFunc = AceType::MakeRefPtr<JsEventFunction<ChangeValueInfo, 1>>(
1681 JSRef<JSFunc>::Cast(jsValue), CreateJsOnWillChangeObj);
1682 auto onWillChange = [execCtx = info.GetExecutionContext(), func = std::move(jsChangeFunc)](
1683 const ChangeValueInfo& changeValue) {
1684 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, true);
1685 ACE_SCORING_EVENT("onWillChange");
1686 auto ret = func->ExecuteWithValue(changeValue);
1687 if (ret->IsBoolean()) {
1688 return ret->ToBoolean();
1689 }
1690 return true;
1691 };
1692 SearchModel::GetInstance()->SetOnWillChangeEvent(std::move(onWillChange));
1693 }
1694
SetStrokeWidth(const JSCallbackInfo & info)1695 void JSSearch::SetStrokeWidth(const JSCallbackInfo& info)
1696 {
1697 if (info.Length() < 1) {
1698 return;
1699 }
1700 CalcDimension value;
1701 if (!ParseLengthMetricsToDimension(info[0], value)) {
1702 value.Reset();
1703 }
1704 SearchModel::GetInstance()->SetStrokeWidth(value);
1705 }
1706
SetStrokeColor(const JSCallbackInfo & info)1707 void JSSearch::SetStrokeColor(const JSCallbackInfo& info)
1708 {
1709 if (info.Length() < 1) {
1710 return;
1711 }
1712 Color strokeColor;
1713 if (!ParseJsColor(info[0], strokeColor)) {
1714 SearchModel::GetInstance()->ResetStrokeColor();
1715 return;
1716 }
1717 SearchModel::GetInstance()->SetStrokeColor(strokeColor);
1718 }
1719
SetEnableAutoSpacing(const JSCallbackInfo & info)1720 void JSSearch::SetEnableAutoSpacing(const JSCallbackInfo& info)
1721 {
1722 bool enabled = false;
1723 if (info.Length() > 0 && info[0]->IsBoolean()) {
1724 enabled = info[0]->ToBoolean();
1725 }
1726 SearchModel::GetInstance()->SetEnableAutoSpacing(enabled);
1727 }
1728
SetOnWillAttachIME(const JSCallbackInfo & info)1729 void JSSearch::SetOnWillAttachIME(const JSCallbackInfo& info)
1730 {
1731 auto jsValue = info[0];
1732 CHECK_NULL_VOID(jsValue->IsFunction());
1733 auto jsOnWillAttachIMEFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSFunc>::Cast(jsValue));
1734 auto onWillAttachIME = [execCtx = info.GetExecutionContext(), func = std::move(jsOnWillAttachIMEFunc)](
1735 const IMEClient& imeClientInfo) {
1736 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
1737 ACE_SCORING_EVENT("onWillAttachIME");
1738 JSRef<JSObject> imeClientObj = JSRef<JSObject>::New();
1739 imeClientObj->SetProperty<int32_t>("nodeId", imeClientInfo.nodeId);
1740 JSRef<JSVal> argv[] = { imeClientObj };
1741 func->ExecuteJS(1, argv);
1742 };
1743 SearchModel::GetInstance()->SetOnWillAttachIME(std::move(onWillAttachIME));
1744 }
1745
SetKeyboardAppearanceConfig(const JSCallbackInfo & info)1746 void JSSearch::SetKeyboardAppearanceConfig(const JSCallbackInfo& info)
1747 {
1748 EcmaVM* vm = info.GetVm();
1749 CHECK_NULL_VOID(vm);
1750 auto jsTargetNode = info[0];
1751 auto* targetNodePtr = jsTargetNode->GetLocalHandle()->ToNativePointer(vm)->Value();
1752 auto* frameNode = reinterpret_cast<NG::FrameNode*>(targetNodePtr);
1753 CHECK_NULL_VOID(frameNode);
1754 if (!info[1]->IsObject()) {
1755 return;
1756 }
1757 NG::KeyboardAppearanceConfig config = JSTextField::ParseKeyboardAppearanceConfig(JSRef<JSObject>::Cast(info[1]));
1758 NG::SearchModelNG::SetKeyboardAppearanceConfig(frameNode, config);
1759 }
1760
UnregisterResource(const std::string & key)1761 void JSSearch::UnregisterResource(const std::string& key)
1762 {
1763 auto frameNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
1764 CHECK_NULL_VOID(frameNode);
1765 auto pattern = frameNode->GetPattern();
1766 CHECK_NULL_VOID(pattern);
1767 pattern->RemoveResObj(key);
1768 }
1769
JsMargin(const JSCallbackInfo & info)1770 void JSSearch::JsMargin(const JSCallbackInfo& info)
1771 {
1772 JSViewAbstract::JsMargin(info);
1773 SearchModel::GetInstance()->SetUserMargin();
1774 }
1775 } // namespace OHOS::Ace::Framework
1776