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 */ 15import ResourceUtil from '../common/ResourceUtil'; 16import SearchData from '../model/SearchData'; 17import LogUtil from '../../../../../../utils/src/main/ets/default/baseUtil/LogUtil'; 18import Log from '../../../../../../utils/src/main/ets/default/baseUtil/LogDecorator'; 19import ConfigData from '../../../../../../utils/src/main/ets/default/baseUtil/ConfigData'; 20 21interface Info { 22 type: number; 23 text: string; 24} 25 26interface InfoItem { 27 index: number; 28 data: Info; 29} 30 31/** 32 * result component 33 */ 34@Component 35export default struct ResultComponent { 36 @Link highlightKeyword: string 37 @State icon: string = '' 38 @State data: SearchData = new SearchData() 39 @State columnSpace: string = '2vp'; 40 private TEXT_TYPE_NORMAL = 1 41 private TEXT_TYPE_KEYWORD = 2 42 43 @Builder 44 HighlightText( 45 spans: Info[], 46 fontColor: Color | Resource, 47 fontSize: Resource, 48 highlightFontColor: Color | Resource) { 49 50 Text() { 51 ForEach(spans.map((item1: Info, index1: number) => { 52 let tmpItem: InfoItem = { index: index1, data: item1 }; 53 return tmpItem; 54 }), (item: InfoItem) => { 55 if (item.data.type == this.TEXT_TYPE_NORMAL) { 56 Span(item.data.text).fontColor(fontColor).fontSize(fontSize).fontWeight(FontWeight.Medium) 57 } else if (item.data.type == this.TEXT_TYPE_KEYWORD) { 58 Span(item.data.text).fontColor(highlightFontColor).fontSize(fontSize).fontWeight(FontWeight.Regular) 59 } 60 }, 61 (item: InfoItem) => item.index.toString() 62 ) 63 } 64 .textAlign(TextAlign.Start) 65 .maxLines(3) 66 .textOverflow({ overflow: TextOverflow.Ellipsis }) 67 } 68 69 build() { 70 Row() { 71 Image(this.icon) 72 .width($r('app.float.item_icon_size')) 73 .height($r('app.float.item_icon_size')) 74 .margin({ right: $r('app.float.sys_elements_margin_horizontal_l') }) 75 .visibility(this.icon ? Visibility.Visible : Visibility.Hidden) 76 .objectFit(ImageFit.Contain); 77 78 Column({ space: this.columnSpace }) { 79 this.HighlightText( 80 this.splitToHighlightText(this.data.keyword), 81 $r('app.color.search_result_text_color'), 82 $r('app.float.search_result_item_title_font_size'), 83 $r('app.color.search_result_text_color_highlight'), 84 ) 85 86 if (this.data.summary) { 87 this.HighlightText( 88 this.splitToHighlightText(this.data.summary), 89 $r('sys.color.ohos_id_color_text_secondary'), 90 $r('app.float.search_result_item_summary_font_size'), 91 $r('app.color.search_result_text_color_highlight'), 92 ) 93 } 94 } 95 .layoutWeight(1) 96 .alignItems(HorizontalAlign.Start); 97 98 Image("/res/image/ic_settings_arrow.svg") 99 .width($r('app.float.item_arrow_width')) 100 .height($r('app.float.item_icon_size')) 101 .margin({ left: $r('app.float.sys_elements_margin_horizontal_m') }) 102 .fillColor($r("sys.color.ohos_id_color_fourth")) 103 } 104 // .height($r('app.float.search_item_height')) 105 .padding({ 106 left: $r('sys.float.ohos_id_card_margin_start'), 107 right: $r('sys.float.ohos_id_card_margin_end') 108 }) 109 .flexShrink(0) 110 .alignItems(VerticalAlign.Center) 111 .align(Alignment.Start) 112 } 113 114 aboutToAppear() { 115 ResourceUtil.getString($r('app.float.distance_2')).then(value => this.columnSpace = value); 116 } 117 118 /** 119 * split to highlight text 120 * @param text 121 */ 122 splitToHighlightText(text: string): Info[] { 123 let spans: Info[] = [] 124 125 let lowerSpans: string[] = text.toLowerCase().split(this.highlightKeyword.toLowerCase()) 126 let keywordStartIndex = 0 127 let keywordLength = this.highlightKeyword.length 128 129 for (let i = 0; i < lowerSpans.length; i++) { 130 let normalText = text.substr(keywordStartIndex, lowerSpans[i].length) 131 spans.push({ 132 type: this.TEXT_TYPE_NORMAL, 133 text: normalText 134 }) 135 LogUtil.debug(ConfigData.TAG + 'ResultComponent splitToHighlightText : i = [' + i + '] push normal : ' + 136 JSON.stringify(normalText)); 137 138 // if not at last, append highlight keyword 139 if (i != lowerSpans.length - 1) { 140 keywordStartIndex += lowerSpans[i].length 141 let keywordText = text.substr(keywordStartIndex, keywordLength) 142 spans.push({ 143 type: this.TEXT_TYPE_KEYWORD, 144 text: keywordText 145 }) 146 LogUtil.debug(ConfigData.TAG + 'ResultComponent splitToHighlightText : i = [' + i + '] push keyword : ' + 147 JSON.stringify(keywordText)); 148 keywordStartIndex += keywordLength 149 } 150 } 151 152 return spans 153 } 154}