1/* 2 * Copyright (c) 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 16if (!('finalizeConstruction' in ViewPU.prototype)) { 17 Reflect.set(ViewPU.prototype, 'finalizeConstruction', () => { }); 18} 19 20const LengthMetrics = requireNapi('arkui.node').LengthMetrics; 21const TEXT_SIZE_BODY1 = { 'id': -1, 'type': -1, params: [`sys.float.ohos_id_text_size_body1`], 'bundleName': '__harDefaultBundleName__', 'moduleName': '__harDefaultModuleName__' }; 22const COLOR_TEXT_SECONDARY = { 'id': -1, 'type': -1, params: [`sys.color.ohos_id_color_text_secondary`], 'bundleName': '__harDefaultBundleName__', 'moduleName': '__harDefaultModuleName__' }; 23const ICON_COLOR_SECONDARY = { 'id': -1, 'type': 10001, params: ['sys.color.ohos_id_color_secondary'], 'bundleName': '__harDefaultBundleName__', 'moduleName': '__harDefaultModuleName__' }; 24const ATOMIC_SERVICE_SEARCH_BG_COLOR = { 'id': -1, 'type': -1, params: [`sys.color.ohos_id_color_text_field_sub_bg`], 'bundleName': '__harDefaultBundleName__', 'moduleName': '__harDefaultModuleName__' }; 25const TEXT_COLOR_PRIMARY = { 'id': -1, 'type': -1, params: [`sys.color.ohos_id_color_text_primary`], 'bundleName': '__harDefaultBundleName__', 'moduleName': '__harDefaultModuleName__' }; 26const FUNCTION_ICON_COLOR = { 'id': -1, 'type': -1, params: [`sys.color.ohos_id_color_primary`], 'bundleName': '__harDefaultBundleName__', 'moduleName': '__harDefaultModuleName__' }; 27const EFFECT_COLOR = { 'id': -1, 'type': -1, params: [`sys.color.ohos_id_color_click_effect`], 'bundleName': '__harDefaultBundleName__', 'moduleName': '__harDefaultModuleName__' }; 28const ICON_SIZE = 16; 29const SELECT_PADDING_LEFT = 6; 30const SELECT_MARGIN_LEFT = 2; 31const FLEX_SHRINK = 0; 32const DIVIDER_OPACITY = 0.5; 33const DIVIDER_MARGIN_LEFT = 2; 34const DIVIDER_MARGIN_RIGHT = 0; 35const ATOMIC_SERVICE_SEARCH_HEIGHT = 40; 36const ATOMIC_SELECT_HEIGHT = 36; 37const ATOMIC_SELECT_BORDER_RADIUS = 20; 38const ATOMIC_DIVIDER_HEIGHT = 20; 39const ICON_WIDTH_AND_HEIGTH = 24; 40const OPERATION_ITEM1_MARGIN_RIGHT = 2; 41const OPERATION_ITEM2_MARGIN_LEFT = 8; 42const SEARCH_OFFSET_X = -5; 43 44export class AtomicServiceSearch extends ViewPU { 45 46 constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) { 47 super(parent, __localStorage, elmtId, extraInfo); 48 if (typeof paramsLambda === 'function') { 49 this.paramsGenerator_ = paramsLambda; 50 } 51 this.__isFunction1Pressed = new ObservedPropertySimplePU(false, this, 'isFunction1Pressed'); 52 this.__isFunction2Pressed = new ObservedPropertySimplePU(false, this, 'isFunction2Pressed'); 53 this.__isSearchPressed = new ObservedPropertySimplePU(false, this, 'isSearchPressed'); 54 this.__showImage = new ObservedPropertySimplePU(true, this, 'showImage'); 55 this.__value = new SynchedPropertyObjectOneWayPU(params.value, this, 'value'); 56 this.__placeholder = new SynchedPropertyObjectOneWayPU(params.placeholder, this, 'placeholder'); 57 this.__select = new SynchedPropertyObjectOneWayPU(params.select, this, 'select'); 58 this.__search = new SynchedPropertyObjectOneWayPU(params.search, this, 'search'); 59 this.operation = undefined; 60 this.controller = new SearchController(); 61 this.setInitiallyProvidedValue(params); 62 this.declareWatch('value', this.onParamsChange); 63 this.declareWatch('select', this.onSelectChange); 64 this.declareWatch('search', this.onSearchChange); 65 this.finalizeConstruction(); 66 } 67 68 setInitiallyProvidedValue(params) { 69 if (params.isFunction1Pressed !== undefined) { 70 this.isFunction1Pressed = params.isFunction1Pressed; 71 } 72 if (params.isFunction2Pressed !== undefined) { 73 this.isFunction2Pressed = params.isFunction2Pressed; 74 } 75 if (params.isSearchPressed !== undefined) { 76 this.isSearchPressed = params.isSearchPressed; 77 } 78 if (params.showImage !== undefined) { 79 this.showImage = params.showImage; 80 } 81 if (params.value === undefined) { 82 this.__value.set(''); 83 } 84 if (params.placeholder === undefined) { 85 this.__placeholder.set('Search'); 86 } 87 if (params.select === undefined) { 88 this.__select.set({}); 89 } 90 if (params.search === undefined) { 91 this.__search.set({ 92 componentBackgroundColor: ATOMIC_SERVICE_SEARCH_BG_COLOR, 93 placeholderFont: { 94 size: TEXT_SIZE_BODY1, 95 }, 96 placeholderColor: COLOR_TEXT_SECONDARY, 97 textFont: { 98 size: TEXT_SIZE_BODY1, 99 }, 100 fontColor: COLOR_TEXT_SECONDARY, 101 searchIcon: { 102 size: ICON_SIZE, 103 color: ICON_COLOR_SECONDARY, 104 }, 105 pressedBackgroundColor: EFFECT_COLOR 106 }); 107 } 108 if (params.operation !== undefined) { 109 this.operation = params.operation; 110 } 111 if (params.controller !== undefined) { 112 this.controller = params.controller; 113 } 114 } 115 116 updateStateVars(params) { 117 this.__value.reset(params.value); 118 this.__placeholder.reset(params.placeholder); 119 this.__select.reset(params.select); 120 this.__search.reset(params.search); 121 } 122 123 purgeVariableDependenciesOnElmtId(rmElmtId) { 124 this.__isFunction1Pressed.purgeDependencyOnElmtId(rmElmtId); 125 this.__isFunction2Pressed.purgeDependencyOnElmtId(rmElmtId); 126 this.__isSearchPressed.purgeDependencyOnElmtId(rmElmtId); 127 this.__showImage.purgeDependencyOnElmtId(rmElmtId); 128 this.__value.purgeDependencyOnElmtId(rmElmtId); 129 this.__placeholder.purgeDependencyOnElmtId(rmElmtId); 130 this.__select.purgeDependencyOnElmtId(rmElmtId); 131 this.__search.purgeDependencyOnElmtId(rmElmtId); 132 } 133 134 aboutToBeDeleted() { 135 this.__isFunction1Pressed.aboutToBeDeleted(); 136 this.__isFunction2Pressed.aboutToBeDeleted(); 137 this.__isSearchPressed.aboutToBeDeleted(); 138 this.__showImage.aboutToBeDeleted(); 139 this.__value.aboutToBeDeleted(); 140 this.__placeholder.aboutToBeDeleted(); 141 this.__select.aboutToBeDeleted(); 142 this.__search.aboutToBeDeleted(); 143 SubscriberManager.Get().delete(this.id__()); 144 this.aboutToBeDeletedInternal(); 145 } 146 147 get isFunction1Pressed() { 148 return this.__isFunction1Pressed.get(); 149 } 150 151 set isFunction1Pressed(newValue) { 152 this.__isFunction1Pressed.set(newValue); 153 } 154 155 get isFunction2Pressed() { 156 return this.__isFunction2Pressed.get(); 157 } 158 159 set isFunction2Pressed(newValue) { 160 this.__isFunction2Pressed.set(newValue); 161 } 162 163 get isSearchPressed() { 164 return this.__isSearchPressed.get(); 165 } 166 167 set isSearchPressed(newValue) { 168 this.__isSearchPressed.set(newValue); 169 } 170 171 get showImage() { 172 return this.__showImage.get(); 173 } 174 175 set showImage(newValue) { 176 this.__showImage.set(newValue); 177 } 178 179 get value() { 180 return this.__value.get(); 181 } 182 183 set value(newValue) { 184 this.__value.set(newValue); 185 } 186 187 get placeholder() { 188 return this.__placeholder.get(); 189 } 190 191 set placeholder(newValue) { 192 this.__placeholder.set(newValue); 193 } 194 195 get select() { 196 return this.__select.get(); 197 } 198 199 set select(newValue) { 200 this.__select.set(newValue); 201 } 202 203 get search() { 204 return this.__search.get(); 205 } 206 207 set search(newValue) { 208 this.__search.set(newValue); 209 } 210 211 aboutToAppear() { 212 this.showImage = this.value?.toString().length === 0 ? true : false; 213 this.initSelectStyle(); 214 this.initSearchStyle(); 215 } 216 217 onParamsChange() { 218 this.showImage = this.value?.toString().length === 0 ? true : false; 219 } 220 221 onSelectChange() { 222 this.initSelectStyle(); 223 } 224 225 onSearchChange() { 226 this.initSearchStyle(); 227 } 228 229 initSelectStyle() { 230 if (typeof this.select !== 'undefined') { 231 if (typeof this.select.selected === 'undefined') { 232 this.select.selected = -1; 233 } 234 if (typeof this.select.font === 'undefined') { 235 this.select.font = { size: TEXT_SIZE_BODY1 }; 236 } 237 if (typeof this.select.fontColor === 'undefined') { 238 this.select.fontColor = TEXT_COLOR_PRIMARY; 239 } 240 } 241 } 242 243 initSearchStyle() { 244 if (typeof this.search !== 'undefined') { 245 if (typeof this.search.componentBackgroundColor === 'undefined') { 246 this.search.componentBackgroundColor = ATOMIC_SERVICE_SEARCH_BG_COLOR; 247 } 248 if (typeof this.search.placeholderFont === 'undefined') { 249 this.search.placeholderFont = { size: TEXT_SIZE_BODY1 }; 250 } 251 if (typeof this.search.placeholderColor === 'undefined') { 252 this.search.placeholderColor = COLOR_TEXT_SECONDARY; 253 } 254 if (typeof this.search.textFont === 'undefined') { 255 this.search.textFont = { size: TEXT_SIZE_BODY1 }; 256 } 257 if (typeof this.search.fontColor === 'undefined') { 258 this.search.fontColor = COLOR_TEXT_SECONDARY; 259 } 260 if (typeof this.search.searchIcon === 'undefined') { 261 this.search.searchIcon = { 262 size: ICON_SIZE, 263 color: ICON_COLOR_SECONDARY, 264 }; 265 } 266 if (typeof this.search.pressedBackgroundColor === 'undefined') { 267 this.search.pressedBackgroundColor = EFFECT_COLOR; 268 } 269 } 270 } 271 272 renderSelect(parent = null) { 273 this.observeComponentCreation2((elmtId, isInitialRender) => { 274 If.create(); 275 if (typeof this.select !== 'undefined' && typeof this.select.options !== 'undefined') { 276 this.ifElseBranchUpdateFunction(0, () => { 277 this.observeComponentCreation2((elmtId, isInitialRender) => { 278 Row.create(); 279 Row.flexShrink(FLEX_SHRINK); 280 }, Row); 281 this.observeComponentCreation2((elmtId, isInitialRender) => { 282 Select.create(this.select?.options); 283 Select.value(this.select?.selectValue); 284 Select.selected(this.select?.selected); 285 Select.onSelect(this.select?.onSelect); 286 Select.menuItemContentModifier.bind(this)(this.select?.menuItemContentModifier); 287 Select.divider(this.select?.divider); 288 Select.font(this.select?.font); 289 Select.fontColor(this.select?.fontColor); 290 Select.selectedOptionBgColor(this.select?.selectedOptionBgColor); 291 Select.selectedOptionFont(this.select?.selectedOptionFont); 292 Select.selectedOptionFontColor(this.select?.selectedOptionFontColor); 293 Select.optionBgColor(this.select?.optionBgColor); 294 Select.optionFont(this.select?.optionFont); 295 Select.optionFontColor(this.select?.optionFontColor); 296 Select.space(this.select?.space); 297 Select.arrowPosition(this.select?.arrowPosition); 298 Select.menuAlign(this.select?.menuAlign?.alignType, this.select?.menuAlign?.offset); 299 Select.optionWidth(this.select?.optionWidth); 300 Select.optionHeight(this.select?.optionHeight); 301 Select.menuBackgroundColor(this.select?.menuBackgroundColor); 302 Select.menuBackgroundBlurStyle(this.select?.menuBackgroundBlurStyle); 303 Select.height(ATOMIC_SELECT_HEIGHT); 304 Select.borderRadius(ATOMIC_SELECT_BORDER_RADIUS); 305 Select.constraintSize({ minHeight: ATOMIC_SELECT_HEIGHT }); 306 Select.padding({ start: LengthMetrics.vp(SELECT_PADDING_LEFT) }); 307 Select.margin({ start: LengthMetrics.vp(SELECT_MARGIN_LEFT) }); 308 Select.backgroundColor(Color.Transparent); 309 }, Select); 310 Select.pop(); 311 Row.pop(); 312 }); 313 } 314 else { 315 this.ifElseBranchUpdateFunction(1, () => { 316 }); 317 } 318 }, If); 319 If.pop(); 320 } 321 322 renderDivider(parent = null) { 323 this.observeComponentCreation2((elmtId, isInitialRender) => { 324 If.create(); 325 if (typeof this.select !== 'undefined' && typeof this.select.options !== 'undefined') { 326 this.ifElseBranchUpdateFunction(0, () => { 327 this.observeComponentCreation2((elmtId, isInitialRender) => { 328 Divider.create(); 329 Divider.vertical(true); 330 Divider.color(Color.Black); 331 Divider.height(ATOMIC_DIVIDER_HEIGHT); 332 Divider.opacity(DIVIDER_OPACITY); 333 Divider.margin({ 334 start: LengthMetrics.vp(DIVIDER_MARGIN_LEFT), 335 end: LengthMetrics.vp(DIVIDER_MARGIN_RIGHT) 336 }); 337 }, Divider); 338 }); 339 } 340 else { 341 this.ifElseBranchUpdateFunction(1, () => { 342 }); 343 } 344 }, If); 345 If.pop(); 346 } 347 348 renderSearch(parent = null) { 349 this.observeComponentCreation2((elmtId, isInitialRender) => { 350 Search.create({ 351 value: this.value?.toString(), 352 placeholder: this.placeholder, 353 controller: this.controller 354 }); 355 Search.key(this.search?.searchKey?.toString()); 356 Search.margin({ start: LengthMetrics.vp(SEARCH_OFFSET_X) }); 357 Search.backgroundColor(Color.Transparent); 358 Search.searchButton(this.search?.searchButton?.searchButtonValue.toString(), this.search?.searchButton?.options); 359 Search.placeholderColor(this.search?.placeholderColor); 360 Search.placeholderFont(this.search?.placeholderFont); 361 Search.textFont(this.search?.textFont); 362 Search.textAlign(this.search?.textAlign); 363 Search.copyOption(this.search?.copyOptions); 364 Search.searchIcon(this.search?.searchIcon); 365 Search.cancelButton({ icon: this.search?.cancelIcon }); 366 Search.fontColor(this.search?.fontColor); 367 Search.caretStyle(this.search?.caretStyle); 368 Search.enableKeyboardOnFocus(this.search?.enableKeyboardOnFocus); 369 Search.selectionMenuHidden(this.search?.hideSelectionMenu); 370 Search.type(this.search?.type); 371 Search.maxLength(this.search?.maxLength); 372 Search.enterKeyType(this.search?.enterKeyType); 373 Search.decoration(this.search?.decoration); 374 Search.letterSpacing(this.search?.letterSpacing); 375 Search.fontFeature(this.search?.fontFeature?.toString()); 376 Search.selectedBackgroundColor(this.search?.selectedBackgroundColor); 377 Search.inputFilter(this.search?.inputFilter?.inputFilterValue, this.search?.inputFilter?.error); 378 Search.textIndent(this.search?.textIndent); 379 Search.minFontSize(this.search?.minFontSize); 380 Search.maxFontSize(this.search?.maxFontSize); 381 Search.editMenuOptions(this.search?.editMenuOptions); 382 Search.enablePreviewText(this.search?.enablePreviewText); 383 Search.enableHapticFeedback(this.search?.enableHapticFeedback); 384 Search.placeholderFont(this.search?.placeholderFont); 385 Search.textFont(this.search?.textFont); 386 Search.searchIcon(this.search?.searchIcon); 387 Search.fontColor(this.search?.fontColor); 388 Search.onCut(this.search?.onCut); 389 Search.onCopy(this.search?.onCopy); 390 Search.onPaste(this.search?.onPaste); 391 Search.onSubmit(this.search?.onSubmit); 392 Search.onDidInsert(this.search?.onDidInsert); 393 Search.onDidDelete(this.search?.onDidDelete); 394 Search.onEditChange(this.search?.onEditChange); 395 Search.onWillInsert(this.search?.onWillInsert); 396 Search.onWillDelete(this.search?.onWillDelete); 397 Search.onContentScroll(this.search?.onContentScroll); 398 Search.onTextSelectionChange(this.search?.onTextSelectionChange); 399 Search.onChange((value, previewText) => { 400 if (previewText?.value.length !== 0) { 401 this.value = previewText?.value; 402 } 403 else { 404 this.value = value; 405 } 406 if (typeof this.search?.onChange !== 'undefined') { 407 this.search?.onChange(value, previewText); 408 } 409 }); 410 Search.onTouch((event) => { 411 if (event && event.type === TouchType.Down) { 412 this.isSearchPressed = true; 413 } 414 else if (event && event.type === TouchType.Up) { 415 this.isSearchPressed = false; 416 } 417 }); 418 }, Search); 419 Search.pop(); 420 } 421 422 renderAuxiliaryItem(parent = null) { 423 this.observeComponentCreation2((elmtId, isInitialRender) => { 424 If.create(); 425 if (typeof this.operation?.auxiliaryItem !== 'undefined' && this.showImage) { 426 this.ifElseBranchUpdateFunction(0, () => { 427 this.observeComponentCreation2((elmtId, isInitialRender) => { 428 Row.create(); 429 Row.onClick(this.operation?.auxiliaryItem.action); 430 Row.flexShrink(FLEX_SHRINK); 431 Row.borderRadius(ATOMIC_SELECT_BORDER_RADIUS); 432 Row.alignItems(VerticalAlign.Center); 433 Row.justifyContent(FlexAlign.Center); 434 Row.width(ATOMIC_SELECT_HEIGHT); 435 Row.height(ATOMIC_SELECT_HEIGHT); 436 Row.margin({ end: LengthMetrics.vp(OPERATION_ITEM1_MARGIN_RIGHT) }); 437 Row.backgroundColor(this.isFunction1Pressed ? this.search?.pressedBackgroundColor : Color.Transparent); 438 Row.onTouch((event) => { 439 if (event && event.type === TouchType.Down) { 440 this.isFunction1Pressed = true; 441 } 442 else if (event && event.type === TouchType.Up) { 443 this.isFunction1Pressed = false; 444 } 445 }); 446 }, Row); 447 this.observeComponentCreation2((elmtId, isInitialRender) => { 448 Image.create(this.operation?.auxiliaryItem?.value); 449 Image.objectFit(ImageFit.Contain); 450 Image.fillColor(FUNCTION_ICON_COLOR); 451 Image.width(ICON_WIDTH_AND_HEIGTH); 452 Image.height(ICON_WIDTH_AND_HEIGTH); 453 Image.draggable(false); 454 }, Image); 455 Row.pop(); 456 }); 457 } 458 else { 459 this.ifElseBranchUpdateFunction(1, () => { 460 }); 461 } 462 }, If); 463 If.pop(); 464 } 465 466 renderIndependentItem(parent = null) { 467 this.observeComponentCreation2((elmtId, isInitialRender) => { 468 If.create(); 469 if (typeof this.operation?.independentItem !== 'undefined') { 470 this.ifElseBranchUpdateFunction(0, () => { 471 this.observeComponentCreation2((elmtId, isInitialRender) => { 472 Row.create(); 473 Row.onClick(this.operation?.independentItem.action); 474 Row.flexShrink(FLEX_SHRINK); 475 Row.borderRadius(ATOMIC_SELECT_BORDER_RADIUS); 476 Row.alignItems(VerticalAlign.Center); 477 Row.justifyContent(FlexAlign.Center); 478 Row.width(ATOMIC_SERVICE_SEARCH_HEIGHT); 479 Row.height(ATOMIC_SERVICE_SEARCH_HEIGHT); 480 Row.margin({ start: LengthMetrics.vp(OPERATION_ITEM2_MARGIN_LEFT) }); 481 Row.backgroundColor(this.isFunction2Pressed ? 482 this.search?.pressedBackgroundColor : this.search?.componentBackgroundColor); 483 Row.onTouch((event) => { 484 if (event && event.type === TouchType.Down) { 485 this.isFunction2Pressed = true; 486 } 487 else if (event && event.type === TouchType.Up) { 488 this.isFunction2Pressed = false; 489 } 490 }); 491 }, Row); 492 this.observeComponentCreation2((elmtId, isInitialRender) => { 493 Image.create(this.operation?.independentItem.value); 494 Image.objectFit(ImageFit.Contain); 495 Image.fillColor(FUNCTION_ICON_COLOR); 496 Image.width(ICON_WIDTH_AND_HEIGTH); 497 Image.height(ICON_WIDTH_AND_HEIGTH); 498 Image.draggable(false); 499 }, Image); 500 Row.pop(); 501 }); 502 } 503 else { 504 this.ifElseBranchUpdateFunction(1, () => { 505 }); 506 } 507 }, If); 508 If.pop(); 509 } 510 511 initialRender() { 512 this.observeComponentCreation2((elmtId, isInitialRender) => { 513 Row.create(); 514 Row.height(ATOMIC_SERVICE_SEARCH_HEIGHT); 515 }, Row); 516 this.observeComponentCreation2((elmtId, isInitialRender) => { 517 Flex.create({ 518 direction: FlexDirection.Row, 519 alignItems: ItemAlign.Center, 520 justifyContent: FlexAlign.Start 521 }); 522 }, Flex); 523 this.observeComponentCreation2((elmtId, isInitialRender) => { 524 Stack.create(); 525 Stack.alignContent(Alignment.End); 526 Stack.borderRadius(ATOMIC_SELECT_BORDER_RADIUS); 527 Stack.backgroundColor(this.isSearchPressed ? 528 this.search?.pressedBackgroundColor : this.search?.componentBackgroundColor); 529 }, Stack); 530 this.observeComponentCreation2((elmtId, isInitialRender) => { 531 Flex.create({ 532 direction: FlexDirection.Row, 533 alignItems: ItemAlign.Center, 534 justifyContent: FlexAlign.Start 535 }); 536 }, Flex); 537 this.renderSelect.bind(this)(); 538 this.renderDivider.bind(this)(); 539 this.renderSearch.bind(this)(); 540 Flex.pop(); 541 this.observeComponentCreation2((elmtId, isInitialRender) => { 542 If.create(); 543 if (typeof this.search?.searchButton === 'undefined') { 544 this.ifElseBranchUpdateFunction(0, () => { 545 this.renderAuxiliaryItem.bind(this)(); 546 }); 547 } 548 else { 549 this.ifElseBranchUpdateFunction(1, () => { 550 }); 551 } 552 }, If); 553 If.pop(); 554 Stack.pop(); 555 this.renderIndependentItem.bind(this)(); 556 Flex.pop(); 557 Row.pop(); 558 } 559 560 rerender() { 561 this.updateDirtyElements(); 562 } 563 564} 565 566export default { AtomicServiceSearch }; 567