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 */ 15import common from '@ohos.app.ability.common'; 16import I18n from '@ohos.i18n'; 17import image from '@ohos.multimedia.image'; 18import uniformDataStruct from '@ohos.data.uniformDataStruct'; 19import { BusinessError } from '@kit.BasicServicesKit'; 20 21export enum FormType { 22 TYPE_BIG = 0, 23 TYPE_MID = 1, 24 TYPE_SMALL = 2 25} 26 27enum TextType { 28 TITLE = 0, 29 DESCRIPTION = 1, 30 APP_NAME = 2 31} 32 33const TAG: string = 'udmf.ContentFormCard'; 34const defaultIcon: string = 35 '82,73,70,70,60,3,0,0,87,69,66,80,86,80,56,32,48,3,0,0,144,67,0,157,1,42,36,2,76,1,62,145,72,161,76,37,164,163,34,3' + 36 '4,151,40,24,176,18,9,105,110,225,117,81,27,243,141,167,87,231,251,1,151,228,76,129,74,56,124,143,240,134,221,17,24' + 37 '5,145,49,195,251,155,103,15,145,254,16,219,162,62,178,38,56,127,115,108,225,242,63,194,27,116,71,214,68,199,15,238' + 38 ',109,156,62,71,248,67,110,136,250,200,152,225,253,205,179,135,200,255,8,109,209,31,89,19,28,63,185,182,112,249,31,' + 39 '225,13,186,35,235,34,99,135,247,54,206,31,35,252,33,183,68,125,100,76,112,254,230,217,195,228,75,0,41,63,219,242,2' + 40 '38,77,44,240,251,18,157,13,186,35,235,34,99,135,247,54,206,31,35,249,8,172,169,162,121,152,235,226,174,0,65,245,14' + 41 '5,49,195,251,155,103,15,145,254,16,219,50,4,52,148,102,170,225,73,64,87,161,183,68,125,100,76,112,254,230,217,195,' + 42 '228,71,209,214,155,210,69,175,155,95,117,236,130,111,176,161,115,26,13,253,205,179,135,200,255,8,109,209,31,89,19,' + 43 '28,63,185,182,112,248,134,3,147,196,80,183,60,143,240,134,221,17,245,145,49,195,251,155,103,9,153,121,194,183,243,' + 44 '118,43,147,107,248,164,83,185,180,54,232,143,172,137,142,31,220,219,56,124,136,157,203,110,159,181,177,87,164,132,' + 45 '51,246,217,120,189,13,186,35,235,34,99,134,241,245,180,72,132,116,112,254,7,167,195,150,227,244,98,234,67,237,155,' + 46 '35,135,102,236,204,223,23,161,183,68,125,100,75,176,70,248,207,116,46,59,232,218,137,15,41,225,38,20,162,105,88,3,' + 47 '59,221,52,249,17,46,76,68,130,195,148,187,103,15,145,253,241,76,10,132,82,146,126,208,179,241,65,64,84,151,15,193,' + 48 '27,58,174,246,254,217,195,225,201,8,103,237,178,241,122,27,116,71,210,161,106,19,234,133,230,77,60,101,201,227,55,' + 49 '59,2,148,71,237,122,200,152,222,202,193,86,94,164,111,28,63,185,180,88,205,133,69,41,39,237,156,62,237,252,33,183,' + 50 '68,126,68,34,111,88,1,159,60,108,76,112,252,104,245,218,227,1,255,172,137,142,31,220,219,56,124,143,239,99,182,153' + 51 ',157,89,206,237,156,41,135,174,215,24,15,76,90,90,193,245,145,49,195,251,155,103,15,145,18,140,226,36,22,28,165,21' + 52 '8,7,174,215,23,217,167,25,36,48,125,100,76,112,254,230,217,195,196,106,61,255,30,253,149,0,0,254,254,226,128,0,0,0' + 53 ',0,0,8,43,156,5,139,91,64,214,164,5,157,168,214,71,99,143,63,110,129,210,71,53,1,30,120,20,41,161,99,5,167,202,76,' + 54 '251,103,189,240,128,146,208,198,255,248,206,215,46,193,53,91,227,66,219,241,255,4,235,164,113,76,186,21,195,174,10' + 55 ',72,252,102,101,0,19,200,26,224,13,190,145,249,137,208,169,128,196,203,52,114,184,23,26,103,126,29,119,157,143,214' + 56 ',115,91,208,138,148,47,18,132,3,189,65,160,138,162,129,225,223,121,199,68,111,66,131,240,170,9,87,178,109,244,143,' + 57 '204,78,245,205,43,87,181,148,112,162,163,53,27,128,197,247,165,165,55,37,6,212,240,48,76,139,191,173,182,51,61,7,1' + 58 '38,70,81,93,158,178,96,58,63,135,99,61,33,123,114,106,17,205,205,245,73,209,248,208,230,67,84,83,67,62,174,199,125' + 59 ',7,42,68,205,119,254,54,95,35,146,246,87,229,105,194,49,134,23,113,205,13,105,146,10,231,32,0,26,210,69,47,127,104' + 60 ',73,141,205,245,214,23,231,110,132,188,27,13,88,8,43,145,225,60,68,0,42,15,95,85,238,25,204,75,166,163,127,0,0'; 61const MAX_CARD_SCALE: number = 1.2; 62const MIN_CARD_SCALE: number = 0.8; 63const SMALL_MIN_CARD_SCALE: number = 0.6; 64const DEFAULT_BIG_CARD_SIZE: number = 200; 65const DEFAULT_MID_CARD_WIDTH: number = 200; 66const DEFAULT_MID_CARD_HEIGHT: number = 100; 67const DEFAULT_SMALL_CARD_WIDTH: number = 137; 68const DEFAULT_SMALL_CARD_HEIGHT: number = 83; 69const DEFAULT_EMPTY_TITLE_WIDTH: number = 70; 70const DEFAULT_EMPTY_APPNAME_WIDTH: number = 40; 71const SMALL_EMPTY_TITLE_WIDTH: number = 50; 72const SMALL_EMPTY_APPNAME_WIDTH: number = 30; 73const DEFAULT_EMPTY_TEXT_RADIUS: number = 2; 74const DEFAULT_EMPTY_DESCRIPTION_WIDTH: string = '100%'; 75const CARD_BACKGROUND: string = '#E6FFFFFF'; 76const APP_NAME_COLOR: string = '#99182431'; 77const DEFAULT_THUMB_BACKGROUND: string = '#CCCCCC'; 78const DEFAULT_FONT_BACKGROUND: string = '#55CCCCCC'; 79const TITLE_FONT_COLOR: string = '#ff182431'; 80const DESCRIPTION_FONT_COLOR: string = '#99182431'; 81const DEFAULT_MID_IMAGE_HEIGHT: number = 72; // 4x2卡片,图片默认高度 82const DEFAULT_SMALL_IMAGE_HEIGHT: number = 59; // 2x1卡片,图片默认高度 83 84interface CardStyle { 85 thumbWidth: number, 86 thumbHeight: number, 87 thumbMarginLeft?: number, 88 titleFontSize: number, 89 titleFontLineHeight: number, 90 titleFontMarginTop: number, 91 descriptionFontSize: number, 92 descriptionLineHeight: number, 93 maxDescriptionFontSize?: number, 94 maxDescriptionLineHeight?: number, 95 descriptionMarginTop: number, 96 dividerMarginTop: number, 97 appNameFontSize: number, 98 appIconSize: number, 99 cardRadius: number, 100 appNameMarginLeft: number, 101 appNameLineHeight: number, 102 cardPadding: number, 103 cardPaddingBottom: number, 104 cardPaddingTop: number 105} 106 107const BIG_CARD_STYLE: CardStyle = { 108 thumbWidth: 200, 109 thumbHeight: 120, 110 titleFontSize: 14, 111 titleFontLineHeight: 16, 112 titleFontMarginTop: 10, 113 descriptionFontSize: 14, 114 descriptionLineHeight: 16, 115 descriptionMarginTop: 4, 116 dividerMarginTop: 5, 117 appNameFontSize: 10, 118 appNameLineHeight: 14, 119 appIconSize: 12, 120 cardRadius: 16, 121 appNameMarginLeft: 6.5, 122 cardPadding: 12, 123 cardPaddingBottom: 10, 124 cardPaddingTop: 5 125} 126 127const MID_CARD_STYLE: CardStyle = { 128 thumbWidth: 36, 129 thumbHeight: 48, 130 thumbMarginLeft: 14, 131 descriptionFontSize: 10, 132 descriptionLineHeight: 12, 133 maxDescriptionFontSize: 14, 134 maxDescriptionLineHeight: 16, 135 descriptionMarginTop: 10, 136 titleFontSize: 14, 137 titleFontLineHeight: 16, 138 titleFontMarginTop: 14, 139 dividerMarginTop: 5, 140 appNameFontSize: 10, 141 appNameLineHeight: 14, 142 appIconSize: 12, 143 cardRadius: 16, 144 appNameMarginLeft: 6.5, 145 cardPadding: 12, 146 cardPaddingBottom: 10, 147 cardPaddingTop: 5 148} 149 150const SMALL_CARD_STYLE: CardStyle = { 151 thumbWidth: 24, 152 thumbHeight: 24, 153 thumbMarginLeft: 8, 154 titleFontSize: 12, 155 titleFontLineHeight: 14, 156 titleFontMarginTop: 9, 157 descriptionFontSize: 10, 158 descriptionLineHeight: 12, 159 maxDescriptionFontSize: 12, 160 maxDescriptionLineHeight: 14, 161 descriptionMarginTop: 4, 162 dividerMarginTop: 5, 163 appNameFontSize: 10, 164 appIconSize: 12, 165 cardRadius: 12, 166 appNameMarginLeft: 4, 167 appNameLineHeight: 12, 168 cardPadding: 8, 169 cardPaddingBottom: 8, 170 cardPaddingTop: 4 171} 172 173@Preview 174@Component 175export struct ContentFormCard { 176 @Prop @Watch('formTypeChange') formType: FormType = FormType.TYPE_MID; 177 private contentFormData: uniformDataStruct.ContentForm | undefined = undefined; 178 private formStyle: CardStyle = MID_CARD_STYLE; 179 private controller: TextController = new TextController(); 180 @State cardScale: number = 1; 181 @Prop @Watch('formSizeChange') formWidth: number = 0; 182 @Prop @Watch('formSizeChange') formHeight: number = 0; 183 @State cardWidth: number = 0; 184 @State cardHeight: number = 0; 185 @State defaultThumbImage: image.PixelMap | undefined = undefined; 186 @State thumbImage: image.PixelMap | undefined = undefined; 187 @State appImage: image.PixelMap | undefined = undefined; 188 @State lineCount: number = 1; 189 @State isMirrorLanguageType: boolean = false; 190 private handleOnClick: () => void = () => { 191 }; 192 193 aboutToAppear(): void { 194 this.initSystemLanguage(); 195 this.initCardStyle(); 196 this.createPixelMap(); 197 } 198 199 aboutToDisappear(): void { 200 this.contentFormData = undefined; 201 this.thumbImage = undefined; 202 this.appImage = undefined; 203 } 204 205 formTypeChange(): void { 206 switch (this.formType) { 207 case FormType.TYPE_BIG: 208 this.formWidth = DEFAULT_BIG_CARD_SIZE; 209 break; 210 case FormType.TYPE_MID: 211 this.formWidth = DEFAULT_MID_CARD_WIDTH; 212 break; 213 default: 214 this.formWidth = DEFAULT_SMALL_CARD_WIDTH; 215 break; 216 } 217 this.initCardStyle(); 218 } 219 220 formSizeChange(): void { 221 this.initCardStyle(); 222 } 223 224 initCardScale(widthScale: number, defaultWidth: number, defaultHeight: number): void { 225 let minScale = this.formType === FormType.TYPE_SMALL ? SMALL_MIN_CARD_SCALE : MIN_CARD_SCALE; 226 if (widthScale > MAX_CARD_SCALE) { 227 this.cardScale = MAX_CARD_SCALE; 228 } else if (widthScale < minScale) { 229 this.cardScale = minScale; 230 } else { 231 this.cardScale = widthScale; 232 } 233 this.cardWidth = defaultWidth * this.cardScale; 234 this.cardHeight = 235 (this.contentFormData?.title === '' && this.formHeight > 0) ? this.formHeight : defaultHeight * this.cardScale; 236 console.info(`${TAG}, widthScale:${this.cardScale}, cardScale: ${this.cardScale}, ` + 237 `cardWidth: ${this.cardWidth}, cardHeight: ${this.cardHeight}`); 238 } 239 240 initCardStyle(): void { 241 let widthScale = 1; 242 switch (this.formType) { 243 case FormType.TYPE_BIG: 244 this.formStyle = BIG_CARD_STYLE; 245 widthScale = this.formWidth ? this.formWidth / DEFAULT_BIG_CARD_SIZE : 1; 246 this.initCardScale(widthScale, DEFAULT_BIG_CARD_SIZE, DEFAULT_BIG_CARD_SIZE); 247 break; 248 case FormType.TYPE_MID: 249 this.formStyle = MID_CARD_STYLE; 250 widthScale = this.formWidth ? this.formWidth / DEFAULT_MID_CARD_WIDTH : 1; 251 this.initCardScale(widthScale, DEFAULT_MID_CARD_WIDTH, DEFAULT_MID_CARD_HEIGHT); 252 break; 253 default: 254 this.formStyle = SMALL_CARD_STYLE; 255 widthScale = this.formWidth ? this.formWidth / DEFAULT_SMALL_CARD_WIDTH : 1; 256 this.initCardScale(widthScale, DEFAULT_SMALL_CARD_WIDTH, DEFAULT_SMALL_CARD_HEIGHT); 257 break; 258 } 259 } 260 261 @Styles 262 thumbStyle() { 263 .width('100%') 264 .padding({ 265 left: this.formStyle.cardPadding * this.cardScale, 266 right: this.formStyle.cardPadding * this.cardScale 267 }) 268 .layoutWeight(1) 269 } 270 271 @Builder 272 ThumbImage() { 273 Column() { 274 if (this.formHeight > 0) { 275 Image(this.thumbImage ? this.thumbImage : this.defaultThumbImage) 276 .objectFit(ImageFit.Contain) 277 .width('100%') 278 .layoutWeight(1) 279 .draggable(false) 280 } else { 281 Image(this.thumbImage ? this.thumbImage : this.defaultThumbImage) 282 .objectFit(ImageFit.Contain) 283 .width('100%') 284 .aspectRatio(this.getAspectRatio()) 285 .draggable(false) 286 } 287 } 288 .size({ width: '100%' }) 289 .layoutWeight(this.formHeight > 0 ? 1 : 0) 290 .backgroundColor(this.thumbImage ? CARD_BACKGROUND : DEFAULT_THUMB_BACKGROUND) 291 } 292 293 @Builder 294 CardDivider() { 295 Divider() 296 .height(1)//.color(CARD_DIVIDER_COLOR) 297 .opacity(0.5) 298 .padding({ 299 left: this.formStyle.cardPadding * this.cardScale, 300 right: this.formStyle.cardPadding * this.cardScale 301 }) 302 } 303 304 @Builder 305 AppView() { 306 Row({ space: this.formStyle.appNameMarginLeft * this.cardScale }) { 307 Image(this.appImage) 308 .width(this.formStyle.appIconSize * this.cardScale) 309 .height(this.formStyle.appIconSize * this.cardScale) 310 .objectFit(ImageFit.Fill) 311 .draggable(false) 312 .alt($r('sys.media.ohos_app_icon')) 313 .borderRadius($r('sys.float.corner_radius_level1')) 314 Text(this.contentFormData?.appName ? this.contentFormData?.appName : ' ') 315 .fontSize(this.formStyle.appNameFontSize * this.cardScale) 316 .fontColor(APP_NAME_COLOR) 317 .maxLines(1) 318 .lineHeight(this.formStyle.appNameLineHeight * this.cardScale) 319 .textOverflow({ overflow: TextOverflow.Ellipsis }) 320 .constraintSize({ minWidth: this.getTextSize(TextType.APP_NAME, this.contentFormData?.appName) }) 321 .backgroundColor(this.getTextBackground(this.contentFormData?.appName)) 322 .fontWeight(FontWeight.Regular) 323 .borderRadius(this.contentFormData?.title === '' ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) 324 .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) 325 .maxFontScale(1) 326 .layoutWeight(1) 327 328 } 329 .padding({ 330 left: this.formStyle.cardPadding * this.cardScale, 331 right: this.formStyle.cardPadding * this.cardScale, 332 top: this.formStyle.cardPaddingTop * this.cardScale, 333 bottom: this.formStyle.cardPaddingBottom * this.cardScale, 334 }) 335 } 336 337 @Builder 338 TitleText() { 339 Text(this.contentFormData?.title) 340 .fontSize(this.formStyle.titleFontSize * this.cardScale) 341 .fontColor(TITLE_FONT_COLOR) 342 .fontWeight(FontWeight.Bold) 343 .maxLines(1) 344 .textOverflow({ overflow: TextOverflow.Ellipsis }) 345 .height(this.formStyle.titleFontLineHeight * this.cardScale) 346 .margin({ top: this.formStyle.titleFontMarginTop * this.cardScale }) 347 .constraintSize({ minWidth: this.getTextSize(TextType.TITLE, this.contentFormData?.title) }) 348 .backgroundColor(this.getTextBackground(this.contentFormData?.title)) 349 .borderRadius(this.contentFormData?.title === '' ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) 350 .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) 351 .maxFontScale(1) 352 } 353 354 @Builder 355 Card4x4() { 356 Column() { 357 Image(this.thumbImage ? this.thumbImage : this.defaultThumbImage) 358 .objectFit(ImageFit.Cover) 359 .width('100%') 360 .height(this.formStyle.thumbHeight * this.cardScale) 361 .backgroundColor(this.thumbImage ? CARD_BACKGROUND : DEFAULT_THUMB_BACKGROUND) 362 .draggable(false) 363 Column() { 364 this.TitleText() 365 Text(this.contentFormData?.description) 366 .fontSize(this.formStyle.descriptionFontSize * this.cardScale) 367 .fontColor(DESCRIPTION_FONT_COLOR) 368 .fontWeight(FontWeight.Regular) 369 .maxLines(1) 370 .textOverflow({ overflow: TextOverflow.Ellipsis }) 371 .constraintSize({ minWidth: this.getTextSize(TextType.DESCRIPTION, this.contentFormData?.description) }) 372 .height(this.formStyle.descriptionLineHeight * this.cardScale) 373 .margin({ top: this.formStyle.descriptionMarginTop * this.cardScale }) 374 .backgroundColor(this.getTextBackground(this.contentFormData?.description)) 375 .fontWeight(FontWeight.Regular) 376 .borderRadius(this.contentFormData?.description ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) 377 .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) 378 .maxFontScale(1) 379 } 380 .alignItems(HorizontalAlign.Start) 381 .width('100%') 382 .padding({ 383 left: this.formStyle.cardPadding * this.cardScale, 384 right: this.formStyle.cardPadding * this.cardScale 385 }) 386 .margin({ bottom: this.formStyle.dividerMarginTop * this.cardScale }) 387 .justifyContent(FlexAlign.Center) 388 389 this.CardDivider() 390 this.AppView() 391 } 392 .size({ width: '100%', height: this.cardHeight }) 393 } 394 395 @Builder 396 DescriptionView() { 397 Text(this.contentFormData?.description ? this.contentFormData?.description : ' ', { controller: this.controller }) 398 .fontColor(DESCRIPTION_FONT_COLOR) 399 .fontWeight(FontWeight.Regular) 400 .maxLines(2) 401 .fontWeight(FontWeight.Regular) 402 .textOverflow({ overflow: TextOverflow.Ellipsis }) 403 .lineHeight((this.lineCount === 1 ? 404 (this.formStyle.maxDescriptionLineHeight ? this.formStyle.maxDescriptionLineHeight : 405 this.formStyle.descriptionLineHeight) : this.formStyle.descriptionLineHeight) * this.cardScale) 406 .fontSize(this.getDescriptionFontSize()) 407 .constraintSize({ minWidth: this.getTextSize(TextType.DESCRIPTION, this.contentFormData?.description) }) 408 .backgroundColor(this.getTextBackground(this.contentFormData?.description)) 409 .borderRadius(this.contentFormData?.description ? 0 : DEFAULT_EMPTY_TEXT_RADIUS) 410 .onAreaChange(() => { 411 let layoutManager: LayoutManager = this.controller.getLayoutManager(); 412 this.lineCount = layoutManager.getLineCount(); 413 }) 414 .direction(this.isMirrorLanguageType ? Direction.Rtl : Direction.Ltr) 415 .maxFontScale(1) 416 } 417 418 @Builder 419 Card4x2() { 420 Column() { 421 if (this.contentFormData?.title === '') { // show the card only thumbData 422 this.ThumbImage() 423 } else { // show the card has thumbData and title,description 424 Row() { 425 Column({ space: this.formStyle.descriptionMarginTop * this.cardScale }) { 426 this.TitleText() 427 this.DescriptionView() 428 } 429 .layoutWeight(1) 430 .alignItems(HorizontalAlign.Start) 431 432 if (this.thumbImage) { 433 Image(this.thumbImage) 434 .width(this.formStyle.thumbWidth * this.cardScale) 435 .height(this.formStyle.thumbHeight * this.cardScale) 436 .objectFit(this.thumbImage ? ImageFit.Cover : ImageFit.Contain) 437 .borderRadius(4) 438 .draggable(false) 439 .margin({ 440 right: this.isMirrorLanguageType ? (this.formStyle.thumbMarginLeft as number * this.cardScale) : 0, 441 left: this.isMirrorLanguageType ? 0 : (this.formStyle.thumbMarginLeft as number * this.cardScale), 442 top: this.formStyle.titleFontMarginTop * this.cardScale 443 }) 444 } 445 } 446 .thumbStyle() 447 .margin({ bottom: this.formStyle.dividerMarginTop * this.cardScale }) 448 .alignItems(VerticalAlign.Top) 449 } 450 451 this.CardDivider(); 452 this.AppView(); 453 } 454 .size({ width: '100%' }) 455 .constraintSize(this.getThumbViewConstraintSize()) 456 } 457 458 @Builder 459 Card2x1() { 460 Column() { 461 if (this.contentFormData?.title === '') { // show the card only thumbData 462 this.ThumbImage() 463 } else { 464 Column() { 465 this.TitleText() 466 Row() { 467 Column() { 468 this.DescriptionView() 469 } 470 .layoutWeight(1) 471 .alignItems(HorizontalAlign.Start) 472 473 if (this.thumbImage) { 474 Image(this.thumbImage) 475 .objectFit(ImageFit.Cover) 476 .draggable(false) 477 .borderRadius($r('sys.float.corner_radius_level2')) 478 .width(this.formStyle.thumbWidth * this.cardScale) 479 .height(this.formStyle.thumbHeight * this.cardScale) 480 .margin({ 481 left: this.isMirrorLanguageType ? 0 : (this.formStyle.thumbMarginLeft as number * this.cardScale), 482 right: this.isMirrorLanguageType ? (this.formStyle.thumbMarginLeft as number * this.cardScale) : 0 483 }) 484 } 485 } 486 .margin({ top: this.formStyle.descriptionMarginTop * this.cardScale }) 487 .layoutWeight(1) 488 } 489 .thumbStyle() 490 .alignItems(HorizontalAlign.Start) 491 .margin({ bottom: this.formStyle.dividerMarginTop * this.cardScale }) 492 } 493 this.CardDivider() 494 this.AppView() 495 } 496 .size({ width: '100%' }) 497 .constraintSize(this.getThumbViewConstraintSize()) 498 } 499 500 build() { 501 Column() { 502 if (this.initSystemLanguage() && this.formType === FormType.TYPE_BIG) { 503 this.Card4x4(); 504 } else if (this.formType === FormType.TYPE_MID) { 505 this.Card4x2(); 506 } else { 507 this.Card2x1(); 508 } 509 } 510 .borderRadius(this.formStyle.cardRadius * this.cardScale) 511 .clip(true) 512 .backgroundColor(CARD_BACKGROUND) 513 .backgroundBlurStyle(BlurStyle.COMPONENT_ULTRA_THICK, 514 { colorMode: ThemeColorMode.LIGHT, adaptiveColor: AdaptiveColor.DEFAULT, scale: 1.0 }) 515 .shadow(ShadowStyle.OUTER_DEFAULT_SM) 516 .width(this.cardWidth) 517 .onClick(() => { 518 this.handleOnClick(); 519 if (!this.contentFormData?.linkUri) { 520 console.warn(`${TAG}, linkUri is null`); 521 return; 522 } 523 try { 524 let context = getContext(this) as common.UIAbilityContext; 525 context.openLink(this.contentFormData?.linkUri, { appLinkingOnly: false, parameters: {} }); 526 } catch (err) { 527 let error = err as BusinessError; 528 console.error(`${TAG}, Failed to openLink, code is ${error.code}, message is ${error.message}`); 529 } 530 }) 531 } 532 533 initSystemLanguage(): boolean { 534 try { 535 this.isMirrorLanguageType = I18n.isRTL(I18n.System.getSystemLanguage()); 536 } catch (err) { 537 let error = err as BusinessError; 538 console.error(`${TAG}, Failed to init system language, code is ${error.code}, message is ${error.message}`); 539 } 540 return true; 541 } 542 543 async getPixelMap(uint: Uint8Array, callback: Function): Promise<void> { 544 let imageResource: image.ImageSource | undefined = undefined; 545 try { 546 imageResource = image.createImageSource(uint.buffer); 547 let pixelMapData = await imageResource?.createPixelMap(); 548 callback(pixelMapData); 549 imageResource.release(); 550 } catch (err) { 551 let error = err as BusinessError; 552 console.error(`${TAG}, Failed to create pixelMap, code is ${error.code}, message is ${error.message}`); 553 } 554 } 555 556 transStringToUint8Array(srcData: string): Uint8Array { 557 const arr: string[] = srcData.split(','); 558 const uint8Array = new Uint8Array(arr.length); 559 arr.forEach((value, index) => { 560 uint8Array[index] = parseInt(value); 561 }) 562 return uint8Array; 563 } 564 565 createPixelMap(): void { 566 let defaultThumbData = this.transStringToUint8Array(defaultIcon); 567 this.getPixelMap(defaultThumbData, (pixelMap: image.PixelMap) => { 568 this.defaultThumbImage = pixelMap; 569 }) 570 571 if (this.contentFormData && this.contentFormData?.thumbData) { 572 if (!(this.contentFormData?.thumbData instanceof Uint8Array)) { 573 console.error(`${TAG}, thumbData is not Uint8Array`); 574 return; 575 } 576 this.getPixelMap(this.contentFormData?.thumbData, (pixelMap: image.PixelMap) => { 577 this.thumbImage = pixelMap; 578 }) 579 } 580 if (this.contentFormData && this.contentFormData?.appIcon) { 581 if (!(this.contentFormData?.appIcon instanceof Uint8Array)) { 582 console.error(`${TAG}, appIcon is not Uint8Array`); 583 return; 584 } 585 this.getPixelMap(this.contentFormData?.appIcon, (pixelMap: image.PixelMap) => { 586 this.appImage = pixelMap; 587 }) 588 } 589 } 590 591 getAspectRatio(): number { 592 let iamgeSize = this.thumbImage?.getImageInfoSync().size; 593 let defaultCardWidth = this.formType === FormType.TYPE_MID ? DEFAULT_MID_CARD_WIDTH : DEFAULT_SMALL_CARD_WIDTH; 594 let defaultImageHeight = 595 this.formType === FormType.TYPE_MID ? DEFAULT_MID_IMAGE_HEIGHT : DEFAULT_SMALL_IMAGE_HEIGHT; 596 if (iamgeSize && this.thumbImage) { 597 if ((iamgeSize.width / iamgeSize.height) > (defaultCardWidth / (defaultImageHeight * MIN_CARD_SCALE))) { 598 return defaultCardWidth / (defaultImageHeight * MIN_CARD_SCALE); 599 } 600 if ((iamgeSize.width / iamgeSize.height) < (defaultCardWidth / (defaultImageHeight * MAX_CARD_SCALE))) { 601 return defaultCardWidth / (defaultImageHeight * MAX_CARD_SCALE); 602 } 603 return iamgeSize.width / iamgeSize.height; 604 } 605 return defaultCardWidth / defaultImageHeight; 606 } 607 608 getTextBackground(text: string | undefined): string { 609 if (text && text.length > 0) { 610 return CARD_BACKGROUND; 611 } 612 return DEFAULT_FONT_BACKGROUND; 613 } 614 615 getTextSize(textType: TextType, text: string | undefined): number | string { 616 if (textType === TextType.TITLE) { 617 if (text === '' || text === undefined || text === null) { 618 if (this.formType === FormType.TYPE_SMALL) { 619 return SMALL_EMPTY_TITLE_WIDTH; 620 } 621 return DEFAULT_EMPTY_TITLE_WIDTH; 622 } 623 return DEFAULT_EMPTY_DESCRIPTION_WIDTH; 624 } 625 if (textType === TextType.APP_NAME) { 626 if (text === '' || text === undefined || text === null) { 627 if (this.formType === FormType.TYPE_SMALL) { 628 return SMALL_EMPTY_APPNAME_WIDTH; 629 } 630 return DEFAULT_EMPTY_APPNAME_WIDTH; 631 } 632 return DEFAULT_EMPTY_DESCRIPTION_WIDTH; 633 } 634 return '100%' 635 } 636 637 getThumbViewConstraintSize(): ConstraintSizeOptions { 638 if (this.contentFormData?.title !== '') { 639 return { maxHeight: this.cardHeight, minHeight: this.cardHeight }; 640 } else { 641 if (this.formHeight > 0) { 642 return { 643 maxHeight: this.formHeight, 644 minHeight: this.formHeight 645 }; 646 } 647 return { 648 maxHeight: this.cardHeight * MAX_CARD_SCALE, 649 minHeight: this.cardHeight * MIN_CARD_SCALE 650 }; 651 } 652 } 653 654 getDescriptionFontSize(): number { 655 return this.lineCount === 1 ? (this.formStyle.maxDescriptionFontSize ? this.formStyle.maxDescriptionFontSize : 656 this.formStyle.descriptionFontSize) : (this.formStyle.descriptionFontSize * this.cardScale); 657 } 658}