• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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