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