1 /*
2  * Copyright (c) 2021 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 "core/components/indexer/indexer_component.h"
17 
18 #include "core/components/common/properties/shadow_config.h"
19 #include "core/components/indexer/indexer_element.h"
20 #include "core/components/indexer/render_indexer_circle.h"
21 
22 namespace OHOS::Ace {
23 
CreateElement()24 RefPtr<Element> Ace::IndexerComponent::CreateElement()
25 {
26     LOGI("[indexer] CreateElement ");
27     return AceType::MakeRefPtr<IndexerElement>();
28 }
29 
CreateRenderNode()30 RefPtr<RenderNode> IndexerComponent::CreateRenderNode()
31 {
32     LOGI("[indexer] CreateRenderNode ");
33     if (circleMode_) {
34         return AceType::MakeRefPtr<RenderIndexerCircle>();
35     } else {
36         return AceType::MakeRefPtr<RenderIndexer>();
37     }
38 }
39 
FormatLabelAlphabet()40 void IndexerComponent::FormatLabelAlphabet()
41 {
42     for (auto& item : indexerLabel_) {
43         if (item == INDEXER_STR_DOT_EX) {
44             item = INDEXER_STR_DOT;
45         }
46     }
47 }
48 
BuildDefaultAlphabet()49 void IndexerComponent::BuildDefaultAlphabet()
50 {
51     defaultAlphaLocal_ = GetU16StrVector(alphabetIndexer_);
52 }
53 
BuildIndexerAlphabet()54 void IndexerComponent::BuildIndexerAlphabet()
55 {
56     BuildDefaultAlphabet();
57     std::vector<std::u16string> alphabet = Localization::GetInstance()->GetIndexAlphabet(); // get alphabet
58     if (alphabet.empty()) {
59         LOGE("fail to build indexer alphabet due to alphabet is empty");
60         return;
61     }
62     FormatLabelAlphabet();
63     // alphabet must begin with "#", and items "." can not be neighbors
64     if (alphabet[0] != INDEXER_STR_SHARP || indexerLabel_[0] != INDEXER_STR_SHARP) {
65         LOGE("fail to build indexer alphabet due to alphabet is wrong");
66         return;
67     }
68 
69     sectionsLocal_.clear();
70     labelLocal_.clear();
71 
72     std::u16string strItem;
73     size_t countAlphabet = 0;
74     for (size_t i = 0; i < indexerLabel_.size(); ++i) {
75         if (indexerLabel_[i] != INDEXER_STR_DOT) {
76             sectionsLocal_.emplace_back(indexerLabel_[i]);
77             labelLocal_.emplace_back(indexerLabel_[i]);
78             ++countAlphabet;
79         } else {
80             if (i == indexerLabel_.size() - 1) { // while this "." is the last item
81                 while (countAlphabet < alphabet.size()) {
82                     strItem += alphabet[countAlphabet];
83                     strItem += INDEXER_STR_SPACE;
84                     ++countAlphabet;
85                 }
86                 sectionsLocal_.emplace_back(strItem);
87                 labelLocal_.emplace_back(indexerLabel_[i]);
88             } else if (indexerLabel_[i + 1] != INDEXER_STR_DOT) { // while the next item is not "."
89                 while ((countAlphabet < alphabet.size()) && (indexerLabel_[i + 1] != alphabet[countAlphabet])) {
90                     strItem += alphabet[countAlphabet];
91                     strItem += INDEXER_STR_SPACE;
92                     ++countAlphabet;
93                 }
94                 sectionsLocal_.emplace_back(strItem);
95                 labelLocal_.emplace_back(indexerLabel_[i]);
96             } else {
97                 // Do nothing while the next item is "." too
98             }
99         }
100         strItem.clear();
101     }
102 }
103 
InitIndexerItemStyle()104 void IndexerComponent::InitIndexerItemStyle()
105 {
106     if (GetCircleMode()) {
107         // Indexer item style when binding list item is not current.
108         normalStyle_.SetFontSize(Dimension(INDEXER_CIRCLE_ITEM_TEXT_SIZE, DimensionUnit::FP));
109         normalStyle_.SetFontWeight(FontWeight::W400);
110         normalStyle_.SetTextColor(Color::WHITE);
111 
112         // Indexer item style when binding list item is current.
113         activeStyle_ = normalStyle_;
114     } else {
115         // Indexer item style when binding list item is not current.
116         normalStyle_.SetFontSize(Dimension(INDEXER_ITEM_TEXT_SIZE, DimensionUnit::FP));
117         normalStyle_.SetFontWeight(FontWeight::W400);
118         normalStyle_.SetTextColor(Color(INDEXER_LIST_COLOR));
119 
120         // Indexer item style when binding list item is current.
121         activeStyle_.SetFontSize(Dimension(INDEXER_LIST_ITEM_TEXT_SIZE, DimensionUnit::FP));
122         activeStyle_.SetFontWeight(FontWeight::W500);
123         activeStyle_.SetTextColor(Color(INDEXER_LIST_ACTIVE_COLOR));
124     }
125 }
126 
BuildArcItem()127 void IndexerComponent::BuildArcItem()
128 {
129     RefPtr<ArcComponent> arcItem = AceType::MakeRefPtr<ArcComponent>();
130     arcItem->SetWidth(itemSize_);
131     arcItem->SetStartAngle(startPosition_);
132     arcItem->SetSweepAngle(arcLength_);
133     arcItem->SetColor(Color(INDEXER_CIRCLE_ARC_COLOR));
134     arcItem->SetShadowWidth(Dimension(INDEXER_CIRCLE_ITEM_SHADOW_RADIUS, DimensionUnit::VP));
135     AppendChild(arcItem);
136     nonItemCount_++;
137 }
138 
BuildBubbleBox()139 void IndexerComponent::BuildBubbleBox()
140 {
141     if (!bubbleEnabled_) {
142         return;
143     }
144     RefPtr<BoxComponent> bubble = AceType::MakeRefPtr<BoxComponent>();
145     bubble->SetFlex(BoxFlex::FLEX_NO);
146     bubble->SetAlignment(Alignment::CENTER);
147     Radius radius = Radius(Dimension(BUBBLE_BOX_SIZE_CIRCLE, DimensionUnit::VP) * HALF);
148     RefPtr<Decoration> back = AceType::MakeRefPtr<Decoration>();
149     if (circleMode_) {
150         bubble->SetWidth(BUBBLE_BOX_SIZE_CIRCLE, DimensionUnit::VP);
151         bubble->SetHeight(BUBBLE_BOX_SIZE_CIRCLE, DimensionUnit::VP);
152         back->SetBackgroundColor(Color(BUBBLE_BG_COLOR_CIRCLE).BlendOpacity(NINETY_OPACITY_IN_PERCENT));
153     } else {
154         // for shadow blur region
155         bubble->SetMargin(Edge(200));
156         bubble->SetWidth(BUBBLE_BOX_SIZE, DimensionUnit::VP);
157         bubble->SetHeight(BUBBLE_BOX_SIZE, DimensionUnit::VP);
158         radius = Radius(Dimension(BUBBLE_BOX_RADIUS, DimensionUnit::VP));
159         back->SetBackgroundColor(Color(BUBBLE_BG_COLOR).BlendOpacity(NINETY_OPACITY_IN_PERCENT));
160         back->AddShadow(ShadowConfig::DefaultShadowL);
161     }
162     back->SetBorderRadius(radius);
163     bubble->SetBackDecoration(back);
164     bubbleText_ = AceType::MakeRefPtr<TextComponent>(StringUtils::Str16ToStr8(INDEXER_STR_SHARP));
165     TextStyle textStyle;
166     textStyle.SetTextAlign(TextAlign::CENTER);
167     if (circleMode_) {
168         textStyle.SetFontSize(Dimension(BUBBLE_FONT_SIZE_CIRCLE, DimensionUnit::FP));
169         textStyle.SetTextColor(Color::WHITE);
170     } else {
171         textStyle.SetFontSize(Dimension(BUBBLE_FONT_SIZE, DimensionUnit::VP));
172         textStyle.SetTextColor(Color(BUBBLE_FONT_COLOR));
173     }
174     bubbleText_->SetTextStyle(textStyle);
175     bubble->SetChild(bubbleText_);
176     RefPtr<DisplayComponent> displayComponent = AceType::MakeRefPtr<DisplayComponent>(bubble);
177     displayComponent->SetOpacity(ZERO_OPACITY);
178     AppendChild(displayComponent);
179     nonItemCount_++;
180 }
181 
BuildIndicatorBox()182 void IndexerComponent::BuildIndicatorBox()
183 {
184     RefPtr<BoxComponent> indicator = AceType::MakeRefPtr<BoxComponent>();
185     indicator->SetWidth(INDEXER_CIRCLE_ITEM_SIZE, DimensionUnit::VP);
186     indicator->SetHeight(INDEXER_CIRCLE_ITEM_SIZE, DimensionUnit::VP);
187     indicator->SetFlex(BoxFlex::FLEX_NO);
188     indicator->SetAlignment(Alignment::CENTER);
189     RefPtr<Decoration> front = AceType::MakeRefPtr<Decoration>();
190     Radius radius = Radius(itemSize_ * HALF);
191     front->SetBorderRadius(radius);
192     front->SetBackgroundColor(Color::TRANSPARENT);
193     indicator->SetFrontDecoration(front);
194     AppendChild(indicator);
195     nonItemCount_++;
196 }
197 
BuildTextItem(const std::u16string & strSection,const std::u16string & strLabel,int32_t itemType)198 void IndexerComponent::BuildTextItem(const std::u16string& strSection, const std::u16string& strLabel, int32_t itemType)
199 {
200     RefPtr<IndexerItemComponent> textItem =
201         AceType::MakeRefPtr<IndexerItemComponent>(strSection, strLabel, itemSize_, circleMode_, false);
202     textItem->SetNormalTextStyle(normalStyle_);
203     textItem->SetActiveTextStyle(activeStyle_);
204     textItem->SetTextStyle(false);
205     textItem->SetItemType(itemType);
206     if (isFirstItem_ || strSection == INDEXER_STR_SHARP || strSection == INDEXER_STR_COLLECT) {
207         textItem->MarkItemPrimary();
208         if (!userDefineList_ || strSection != INDEXER_STR_SHARP) {
209             isFirstItem_ = false;
210         }
211     }
212     listItem_.emplace_back(textItem);
213     AppendChild(textItem);
214     ++itemCount_;
215 }
216 
BuildCollapseItem()217 void IndexerComponent::BuildCollapseItem()
218 {
219     RefPtr<IndexerItemComponent> collapseItem = AceType::MakeRefPtr<IndexerItemComponent>(
220         INDEXER_STR_COLLAPSE, INDEXER_STR_COLLAPSE, itemSize_, circleMode_, true);
221     collapseItem->SetNormalTextStyle(normalStyle_);
222     collapseItem->SetActiveTextStyle(activeStyle_);
223     collapseItem->SetTextStyle(false);
224     collapseItem->MarkItemPrimary();
225     listItem_.emplace_back(collapseItem);
226     AppendChild(collapseItem);
227     ++itemCount_;
228     hasCollapseItem_ = true;
229 }
230 
BuildIndexerItems()231 void IndexerComponent::BuildIndexerItems()
232 {
233     uint32_t length = static_cast<uint32_t>(labelLocal_.size());
234     if (length == 0) {
235         LOGE("[indexer] invalid section string");
236         return;
237     }
238 
239     // add arc first while circle mode
240     if (GetCircleMode()) {
241         BuildArcItem();
242         BuildIndicatorBox();
243     }
244     BuildBubbleBox();
245     itemCount_ = 0;
246 
247     // add “*” item while circle mode
248     if (GetCircleMode() && !userDefineList_) {
249         BuildTextItem(INDEXER_STR_COLLECT, INDEXER_STR_COLLECT);
250     }
251     // add "#" first
252     if (!userDefineList_) {
253         BuildTextItem(INDEXER_STR_SHARP, INDEXER_STR_SHARP);
254     }
255     // add indexer items except '#'
256     isFirstItem_ = true;
257     for (uint32_t i = 0; i < length; ++i) {
258         std::u16string strItem = labelLocal_[i];
259         if (!userDefineList_ && strItem == INDEXER_STR_SHARP) {
260             continue;
261         }
262         BuildTextItem(sectionsLocal_[i], strItem);
263     }
264 
265     if (circleMode_ && multiLanguageEnabled_) {
266         isFirstItem_ = true;
267         // add default alphabet indexer
268         uint32_t count = defaultAlphaLocal_.size();
269         for (uint32_t i = 0; i < count; ++i) {
270             std::u16string strItem = defaultAlphaLocal_[i];
271             BuildTextItem(strItem, strItem, 1);
272         }
273         ++maxShowCount_;
274         if (userDefineList_ && indexerLabel_[0] != INDEXER_STR_COLLECT) {
275             --maxShowCount_;
276         }
277     }
278     isFirstItem_ = false;
279 
280     // add collapse item while circle mode
281     if (GetCircleMode() && itemCount_ > INDEXER_COLLAPSE_ITEM_COUNT) {
282         BuildCollapseItem();
283     }
284     if (GetCircleMode()) {
285         RefPtr<ArcComponent> arc =
286             AceType::DynamicCast<ArcComponent>(GetChildren().empty() ? nullptr : GetChildren().front());
287         if (arc) {
288             double arcLen = itemCount_ < maxShowCount_ ?
289                 INDEXER_ARC_LENGTH / maxShowCount_ * (itemCount_ - 1) : INDEXER_ARC_LENGTH;
290             arc->SetSweepAngle(arcLen);
291         }
292     }
293     LOGI("[indexer] BuildIndexerItems circleMode:%{public}d, itemCount_:%{public}d", circleMode_, itemCount_);
294 }
295 
GetIndexerItem(const std::string & indexKey)296 RefPtr<IndexerItemComponent> IndexerComponent::GetIndexerItem(const std::string& indexKey)
297 {
298     RefPtr<IndexerItemComponent> ret = nullptr;
299     if (indexKey.empty()) {
300         LOGE("[indexer] indexKey is NULL");
301         return ret;
302     }
303 
304     LOGI("[indexer] GetIndexerItem section: %{public}s", indexKey.c_str());
305     for (const auto& item : listItem_) {
306         if (item->IsCorrectItem(indexKey)) {
307             LOGI("[indexer] section: %{public}s", StringUtils::Str16ToStr8(item->GetSectionStr()).c_str());
308             ret = item;
309             break;
310         }
311     }
312     return ret;
313 }
314 
AddItemIndexKey(const std::string & indexKey,const std::string & headStyle)315 int32_t IndexerComponent::AddItemIndexKey(const std::string& indexKey, const std::string& headStyle)
316 {
317     int32_t itemIndex = INDEXER_INVALID_INDEX;
318     if (!list_) {
319         LOGE("[indexer] AddItemIndexKey List ptr is NULL");
320         return itemIndex;
321     }
322 
323     if (indexKey.empty()) {
324         LOGI("[indexer] indexKey is NULL, add to Sharp area.");
325         // add to sharp section, while indexkey is Null
326         return AddItemToSharp(indexKey, headStyle);
327     }
328 
329     for (const auto& item : listItem_) {
330         if (item && (item->IsCorrectItem(indexKey))) {
331             // add section head
332             if (item->GetKeyCount() == 0 && !GetCircleMode()) {
333                 AddSectionHead(item, headStyle);
334             }
335             // add index key
336             itemIndex = static_cast<int32_t>(item->AddIndexKey(indexKey));
337             break;
338         }
339     }
340 
341     // add to sharp section, while indexkey is number
342     if (itemIndex == INVALID_INDEX) {
343         itemIndex = AddItemToSharp(indexKey, headStyle);
344     } else {
345         UpdateSectionIndex();
346     }
347 
348     return itemIndex;
349 }
350 
AddItemToSharp(const std::string & indexKey,const std::string & headStyle)351 int32_t IndexerComponent::AddItemToSharp(const std::string& indexKey, const std::string& headStyle)
352 {
353     // find the # section
354     RefPtr<IndexerItemComponent> itemPtr = nullptr;
355     if (!listItem_.empty()) {
356         for (const auto& item : listItem_) {
357             if (item && (item->GetSectionStr() == INDEXER_STR_SHARP)) {
358                 itemPtr = item;
359                 break;
360             }
361         }
362     }
363     if (!itemPtr) {
364         LOGE("[indexer] AddItemToSharp get # section failed");
365         return 0;
366     }
367 
368     // add section head
369     if (itemPtr->GetKeyCount() == 0 && !GetCircleMode()) {
370         AddSectionHead(itemPtr, headStyle);
371     }
372     // add index key
373     int32_t itemIndex = static_cast<int32_t>(itemPtr->AddIndexKey(indexKey));
374     // update section head index
375     UpdateSectionIndex();
376 
377     return itemIndex;
378 }
379 
PrintItemInfo() const380 void IndexerComponent::PrintItemInfo() const
381 {
382     for (const auto& item : listItem_) {
383         item->PrintIndexerItem();
384     }
385 }
386 
AddSectionHead(const RefPtr<IndexerItemComponent> & indexerItem,const std::string & headStyleStr)387 int32_t IndexerComponent::AddSectionHead(
388     const RefPtr<IndexerItemComponent>& indexerItem, const std::string& headStyleStr)
389 {
390     int32_t sectionHeadIndex = INDEXER_INVALID_INDEX;
391     if (GetCircleMode()) {
392         LOGI("[indexer] Circle Mode, cancel section head adding");
393         return sectionHeadIndex;
394     }
395 
396     if (!list_) {
397         LOGE("[indexer] List ptr is NULL");
398         return sectionHeadIndex;
399     }
400 
401     if (!indexerItem) {
402         LOGE("[indexer] Invalid indexerItem ");
403         return sectionHeadIndex;
404     }
405 
406     std::string strSectionHeadLabel = StringUtils::Str16ToStr8(indexerItem->GetLabelStr());
407     if (strSectionHeadLabel.empty()) {
408         LOGE("[indexer] Invalid Section head, strSectionHead:%{public}s", strSectionHeadLabel.c_str());
409         return sectionHeadIndex;
410     }
411 
412     // [indexer] Section head style need check
413     RefPtr<TextComponent> text = AceType::MakeRefPtr<TextComponent>(strSectionHeadLabel);
414     TextStyle headStyle;
415     if (circleMode_) {
416         headStyle.SetFontSize(Dimension(INDEXER_CIRCLE_ITEM_TEXT_SIZE, DimensionUnit::FP));
417     } else {
418         headStyle.SetFontSize(Dimension(INDEXER_ITEM_TEXT_SIZE, DimensionUnit::FP));
419     }
420     headStyle.SetFontWeight(FontWeight::W500);
421     headStyle.SetTextColor(Color::BLACK);
422     text->SetTextStyle(headStyle);
423     RefPtr<BoxComponent> box = AceType::MakeRefPtr<BoxComponent>();
424     box->SetFlex(BoxFlex::FLEX_X);
425     box->SetDeliverMinToChild(false);
426     box->SetAlignment(Alignment::CENTER);
427     box->SetColor(Color::WHITE);
428     box->SetChild(text);
429     RefPtr<ListItemComponent> listItem = AceType::MakeRefPtr<ListItemComponent>(headStyleStr, box);
430     listItem->SetSticky(true);
431     listItem->SetIndexKey(strSectionHeadLabel);
432     RefPtr<ComposedComponent> composedItem =
433         AceType::MakeRefPtr<ComposedComponent>("section", "sectionComposed", listItem);
434     sectionHeadIndex = indexerItem->GetSectionIndex();
435     list_->InsertChild(sectionHeadIndex, composedItem);
436     LOGI("[indexer] strSectionHeadLabel:%{public}s, headStyle:%{public}s index:%{public}d",
437         strSectionHeadLabel.c_str(), headStyleStr.c_str(), sectionHeadIndex);
438     return sectionHeadIndex;
439 }
440 
RemoveSectionHead(int32_t index)441 bool IndexerComponent::RemoveSectionHead(int32_t index)
442 {
443     bool ret = false;
444     if (GetCircleMode()) {
445         return ret;
446     }
447 
448     if (!list_) {
449         LOGE("[indexer] RemoveSectionHead List ptr is NULL");
450         return ret;
451     }
452 
453     for (const auto& item : list_->GetChildren()) {
454         RefPtr<ListItemComponent> listItem = ListItemComponent::GetListItem(item);
455         if (listItem && listItem->GetIndex() == index) {
456             list_->RemoveChild(item);
457             ret = true;
458             break;
459         }
460     }
461 
462     return ret;
463 }
464 
RemoveItemIndexKey(const std::string & indexKey)465 bool IndexerComponent::RemoveItemIndexKey(const std::string& indexKey)
466 {
467     bool ret = false;
468     if (!list_) {
469         LOGE("[indexer] RemoveItemIndexKey List ptr is NULL");
470         return ret;
471     }
472 
473     if (indexKey.empty()) {
474         LOGI("[indexer] RemoveItemIndexKey indexKey is NULL");
475         // remove item while the index is null
476         return RemoveItemFromSharp(indexKey);
477     }
478 
479     for (const auto& item : listItem_) {
480         if (item && (item->IsCorrectItem(indexKey))) {
481             int32_t sectionHeadIndex = item->GetSectionIndex();
482             // remove index key
483             ret = item->RemoveIndexKey(indexKey);
484             // remove section head
485             if (item->GetKeyCount() == 0 && !GetCircleMode()) {
486                 RemoveSectionHead(sectionHeadIndex);
487             }
488             break;
489         }
490     }
491 
492     if (ret) {
493         // update section head index
494         UpdateSectionIndex();
495     } else {
496         // remove item while indexkey is number, low probable case, put it last
497         ret = RemoveItemFromSharp(indexKey);
498     }
499 
500     return ret;
501 }
502 
RemoveItemFromSharp(const std::string & indexKey)503 bool IndexerComponent::RemoveItemFromSharp(const std::string& indexKey)
504 {
505     // remove item from "#" section
506     bool ret = false;
507     if (!list_) {
508         LOGE("[indexer] RemoveItemFromSharp List ptr is NULL");
509         return ret;
510     }
511 
512     // find section "#"
513     RefPtr<IndexerItemComponent> itemPtr = nullptr;
514     if (!listItem_.empty()) {
515         for (const auto& item : listItem_) {
516             if (item && (item->GetSectionStr() == INDEXER_STR_SHARP)) {
517                 itemPtr = item;
518                 break;
519             }
520         }
521     }
522     if (!itemPtr) {
523         LOGE("[indexer] RemoveItemFromSharp get # section failed");
524         return ret;
525     }
526 
527     ret = itemPtr->RemoveIndexKey(indexKey);
528     if (!ret) {
529         LOGE("[indexer] RemoveItemFromSharp remove IndexKey failed");
530         return ret;
531     }
532 
533     // update section head index
534     UpdateSectionIndex();
535 
536     return ret;
537 }
538 
GetSectionIndexInList(const std::string & indexKey)539 int32_t IndexerComponent::GetSectionIndexInList(const std::string& indexKey)
540 {
541     int32_t index = INVALID_INDEX;
542     RefPtr<IndexerItemComponent> item = GetIndexerItem(indexKey);
543     if (item) {
544         index = item->GetSectionIndex();
545     }
546     return index;
547 }
548 
GetSectionIndexInIndexer(int32_t index)549 int32_t IndexerComponent::GetSectionIndexInIndexer(int32_t index)
550 {
551     int32_t count = 0;
552     if (index <= 0) {
553         return count;
554     }
555     for (const auto& item : listItem_) {
556         if (item) {
557             if (index < item->GetSectionIndex()) {
558                 break;
559             }
560         }
561         count++;
562     }
563     return count - 1;
564 }
565 
UpdateSectionIndex()566 void IndexerComponent::UpdateSectionIndex()
567 {
568     // update section head index
569     if (listItem_.empty()) {
570         LOGE("[indexer] UpdateSectionIndex listItem_ is empty");
571         return;
572     }
573 
574     int32_t sectionIndex = listItem_.front()->GetSectionIndex();
575     for (const auto& item : listItem_) {
576         if (!item) {
577             continue;
578         }
579         item->SetSectionIndex(sectionIndex);
580         if (item->GetKeyCount() != 0) {
581             sectionIndex = sectionIndex + static_cast<int32_t>(item->GetKeyCount()) + 1;
582             if (GetCircleMode()) {
583                 --sectionIndex;
584             }
585         }
586     }
587 }
588 
589 } // namespace OHOS::Ace
590