• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}