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