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 16import { BusinessError } from '@kit.BasicServicesKit'; 17import { photoAccessHelper } from '@kit.MediaLibraryKit'; 18import { logger } from '../utils/Logger'; 19 20// TODO:扁平化ID设置 21const ID_TEXT_INPUT: string = 'id_text_input'; 22const ID_TEXT_PUSH: string = 'id_text_publish'; 23 24const typeVideo: string = 'video'; 25const typeImage: string = 'image'; 26const TAG: string = 'publishmultimediaupdates'; 27 28/** 输入评论弹窗,用于输入文字和图片评论 29 * 实现步骤: 30 * 1.点击预制图片、发布按钮 31 * 2.点击预制图片时通过photoAccessHelper接口拉起图库 32 * 3.选择图库资源后获取照片、视频返回地址,并显示在组件中 33 * 4.点击发布按钮,将评论添加到列表中 34 */ 35 36@CustomDialog 37export struct CommentInputDialog { 38 // 选择的照片 39 @State selectedImages: ResourceStr = $r('app.media.add'); 40 // 选择的视频 41 @State selectedVideo: ResourceStr = $r('app.media.add_video'); 42 // 输入的文字 43 @State text: string = ''; 44 // 使用@Link将CustomDialog内的数据进行链接 45 @Link textInComment: string; 46 @Link imagesInComment: string; 47 @Link videoInComment: string; 48 // 设置自定义弹窗类型 49 @Link dialogType: string; 50 maxSelectMedia: number = 1; 51 videoController: VideoController = new VideoController() 52 controller?: CustomDialogController; 53 // 发布接口,用于主页面更新评论数据 54 publish: () => void = (): void => { 55 } 56 57 async getPictureFromAlbum() { 58 // 拉起相册,选择图片 59 let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); 60 // 选择图库内媒体资源种类 61 photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE; 62 // 设置最大媒体文件选择数量 63 photoSelectOptions.maxSelectNumber = this.maxSelectMedia; 64 // 创建photoPicker 65 let photoPicker = new photoAccessHelper.PhotoViewPicker(); 66 // 使用photoAccessHelper获取媒体资源信息 67 photoPicker.select(photoSelectOptions).then((photoSelectResult) => { 68 if (photoSelectResult !== null && photoSelectResult !== undefined) { 69 // 获取对应资源文件uri地址 70 this.selectedImages = photoSelectResult.photoUris[0]; 71 this.imagesInComment = photoSelectResult.photoUris[0]; 72 } 73 }).catch((err: BusinessError) => { 74 logger.error(TAG, 75 `getPictureFromAlbum PhotoViewPicker.select failed, error code: ${err.code}, message: ${err.message}.`); 76 }) 77 } 78 79 async getVideoFromAlbum() { 80 // 拉起相册,选择视频 81 let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); 82 photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE; 83 photoSelectOptions.maxSelectNumber = this.maxSelectMedia; 84 let photoPicker = new photoAccessHelper.PhotoViewPicker(); 85 photoPicker.select(photoSelectOptions).then((photoSelectResult) => { 86 if (photoSelectResult !== null && photoSelectResult !== undefined) { 87 // 获取对应资源文件uri地址 88 this.selectedVideo = photoSelectResult.photoUris[0]; 89 this.videoInComment = photoSelectResult.photoUris[0]; 90 } 91 }).catch((err: BusinessError) => { 92 logger.error(TAG, 93 `getVideoFromAlbum PhotoViewPicker.select failed, error code: ${err.code}, message: ${err.message}.`); 94 }) 95 } 96 97 build() { 98 Column() { 99 RelativeContainer() { 100 TextInput() 101 .height($r('app.integer.image_comment_text_input_height')) 102 .padding({ 103 left: $r('app.integer.image_comment_text_input_padding_left'), 104 right: $r('app.integer.image_comment_text_input_padding_right'), 105 top: $r('app.integer.image_comment_text_input_padding_top'), 106 bottom: $r('app.integer.image_comment_text_input_padding_bottom') 107 }) 108 .margin({ 109 right: $r('app.integer.image_comment_text_input_margin_top') 110 }) 111 .onChange((textInComment: string) => { 112 this.text = textInComment; 113 }) 114 .defaultFocus(true) 115 .alignRules({ 116 // TODO:高性能知识点:使用相对布局组件RelativeContainer,子组件通过alignRules接口将父组件或者其他组件设为锚点,可使布局扁平化,有利于性能提升 117 top: { anchor: '__container__', align: VerticalAlign.Top }, 118 bottom: { anchor: '__container__', align: VerticalAlign.Bottom }, 119 left: { anchor: '__container__', align: HorizontalAlign.Start }, 120 right: { anchor: ID_TEXT_PUSH, align: HorizontalAlign.Start } 121 }) 122 .id(ID_TEXT_INPUT) 123 Button($r('app.string.image_comment_publish')) 124 .width($r('app.integer.image_comment_button_publish_width')) 125 .height($r('app.integer.image_comment_button_publish_height')) 126 .borderRadius($r('app.integer.image_comment_button_publish_border_radius')) 127 .backgroundColor($r('app.color.image_comment_button_publish_background')) 128 .fontColor(Color.White) 129 .onClick(() => { 130 if (this.controller) { 131 this.textInComment = this.text; 132 this.publish(); 133 this.controller.close(); 134 this.textInComment = ''; 135 this.imagesInComment = ''; 136 this.videoInComment = ''; 137 } 138 }) 139 .alignRules({ 140 top: { anchor: '__container__', align: VerticalAlign.Top }, 141 bottom: { anchor: '__container__', align: VerticalAlign.Bottom }, 142 right: { anchor: '__container__', align: HorizontalAlign.End } 143 }) 144 .id(ID_TEXT_PUSH) 145 } 146 .height($r('app.integer.image_comment_relative_container_input_height')) 147 148 if (this.dialogType == typeImage) { 149 Image(this.selectedImages) 150 .width($r('app.integer.publish_multimedia_updates_single_image_width')) 151 .height($r('app.integer.publish_multimedia_updates_single_image_height')) 152 .borderRadius($r('app.integer.publish_multimedia_updates_single_image_radius')) 153 .offset({ right: $r('app.integer.media_offset_to_right') }) 154 .onClick(() => { 155 // 选取照片 156 this.getPictureFromAlbum() 157 }) 158 .id('select_picture_button') 159 } 160 161 if (this.dialogType == typeVideo) { 162 Video({ 163 src: this.selectedVideo, 164 previewUri: this.selectedImages, 165 controller: this.videoController 166 }) 167 .width($r('app.integer.publish_multimedia_updates_single_image_width')) 168 .height($r('app.integer.publish_multimedia_updates_single_image_height')) 169 .borderRadius($r('app.integer.publish_multimedia_updates_single_image_radius')) 170 .controls(false) 171 .offset({ right: $r('app.integer.media_offset_to_right') }) 172 .autoPlay(true) 173 .objectFit(ImageFit.Cover) 174 .muted(true) 175 .onClick(() => { 176 ///选取视频 177 this.getVideoFromAlbum() 178 }) 179 .id('select_video_button') 180 181 } 182 183 } 184 .padding($r('app.integer.image_comment_column_input_padding')) 185 .backgroundColor(Color.White) 186 // 添加y轴偏移量,否则弹窗和输入法间会有空白 187 .offset({ 188 y: $r('app.integer.image_comment_column_input_dialog_offset_y') 189 }) 190 } 191}