1/* 2 * Copyright (c) 2023 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 router from '@ohos.router'; 17import { TrendsItem } from '../commonComponent/TrendsItem'; 18import { CommentData } from '../model/TrendsDataSource'; 19import { makeCommentDataLocal, promptActionFn } from '../model/DataFactory'; 20import { Trends, UserInfo, ContentsType } from '../model/BaseMsg'; 21import { PasteControl } from '../authorizedControl/PasteControl'; 22import Constants from '../utils/Constants'; 23 24@Component 25export struct CommentDetailView { 26 // 初始化输入框value值 27 @State textInputValue: string = ''; 28 @State isSelectionMenuHidden: boolean = false; 29 // 初始化是否显示复制粘贴文本选择器 30 @State isTextInputShow: boolean = false; 31 // 初始化键盘高度 32 @StorageLink('keyboardHeight') keyboardHeight: number = 0; 33 // 评论数据属性 34 @Provide commentDataSource: CommentData = new CommentData(); 35 // 获取动态信息 36 private trendsItemData: Trends = (router.getParams() as Record<string, Object>)['trendsData'] as Trends; 37 // Scroll控制器 38 private scroller: Scroller = new Scroller(); 39 // 输入框控制器 40 private controller: TextInputController = new TextInputController(); 41 42 /** 43 * 自定义组件 评论 点赞 44 * @param image 图片路径 text 文本内容 featureIndex 下标 45 */ 46 @Builder 47 FeatureBuilder(image: Resource, text: Resource, featureIndex: number) { 48 Column() { 49 Image(image) 50 .width($r('app.integer.layout_size_28')) 51 .height($r('app.integer.layout_size_28')) 52 .objectFit(ImageFit.Contain) 53 Text(text) 54 .fontSize($r('app.integer.layout_size_12')) 55 .id('commentButton') 56 } 57 .justifyContent(FlexAlign.Center) 58 .height(56) 59 .onClick(() => { 60 if (featureIndex !== 1) { 61 promptActionFn($r('app.string.feature_development')); 62 return; 63 } 64 this.isTextInputShow = true; 65 }) 66 } 67 68 build() { 69 Stack({ alignContent: Alignment.Bottom }) { 70 Flex({ direction: FlexDirection.Column }) { 71 // 标题 72 TitleBar() 73 Scroll(this.scroller) { 74 Column() { 75 // 动态详情信息 76 TrendsItem({ trendsItemData: this.trendsItemData, isDetailPage: true, isVisible: false }) 77 .width('90%') 78 // 评论区 79 CommentArea() 80 } 81 } 82 }.width('100%') 83 .height('100%') 84 85 // 输入框 86 if (this.isTextInputShow) { 87 Row() { 88 if (this.isSelectionMenuHidden) { 89 PasteControl({ isSelectionMenuHidden: $isSelectionMenuHidden, textInputValue: $textInputValue }) 90 } 91 92 Image(this.trendsItemData.user.userImage) 93 .width($r('app.integer.layout_size_40')) 94 .height($r('app.integer.layout_size_40')) 95 .borderRadius($r('app.integer.layout_size_20')) 96 TextInput({ 97 text: this.textInputValue, 98 placeholder: $r('app.string.add_comment'), 99 controller: this.controller 100 }) 101 .id('comment_add') 102 .placeholderFont({ size: 14, weight: 400 }) 103 .backgroundColor(Color.White) 104 .selectionMenuHidden(true) 105 .enterKeyType(EnterKeyType.Send) 106 .width($r('app.integer.layout_size_400')) 107 .height($r('app.integer.layout_size_40')) 108 .fontSize($r('app.integer.layout_size_14')) 109 .fontColor(Color.Black) 110 .onChange((value: string) => { 111 this.textInputValue = value; 112 }) 113 .onSubmit(async () => { 114 this.trendsItemData.contents.text = this.textInputValue; 115 this.trendsItemData.likeCount = 0; 116 this.commentDataSource.pushData(this.trendsItemData); 117 this.textInputValue = ''; 118 this.isTextInputShow = false; 119 }) 120 .gesture(LongPressGesture({ repeat: true, duration: 300 }) 121 .onAction((event?: GestureEvent) => { 122 this.isSelectionMenuHidden = true; 123 })) 124 125 }.width('100%') 126 .backgroundColor(Color.White) 127 .padding($r('app.integer.layout_size_10')) 128 .border({ 129 width: { top: Constants.BORDERWIDTH }, 130 color: '#fffffbfb', 131 }) 132 } else { 133 Column() { 134 Divider() 135 .vertical(false) 136 .strokeWidth('1') 137 .color($r('app.color.font_color_182431')) 138 .opacity(0.15) 139 Row() { 140 this.FeatureBuilder($r('app.media.ic_share'), $r('app.string.share'), Constants.TAB_INDEX_0) 141 this.FeatureBuilder($r('app.media.ic_message'), $r('app.string.comment'), Constants.TAB_INDEX_1) 142 this.FeatureBuilder($r('app.media.ic_thumbsup'), $r('app.string.like'), Constants.TAB_INDEX_2) 143 } 144 .width('100%') 145 .justifyContent(FlexAlign.SpaceAround) 146 .alignItems(VerticalAlign.Center) 147 .backgroundColor('#F1F3F5') 148 } 149 150 } 151 }.padding({ bottom: px2vp((this.keyboardHeight)) }) 152 .expandSafeArea([SafeAreaType.KEYBOARD]) 153 } 154} 155 156@Component 157struct TitleBar { 158 build() { 159 Row(){ 160 Row() { 161 Image($r('app.media.ic_public_back')) 162 .id('backBtn') 163 .width($r('app.integer.layout_size_24')) 164 .height($r('app.integer.layout_size_24')) 165 .onClick(() => { 166 router.back(); 167 }) 168 Row() { 169 Image($r('app.media.ic_collect')) 170 .width($r('app.integer.layout_size_24')) 171 .height($r('app.integer.layout_size_24')) 172 .onClick(() => { 173 promptActionFn($r('app.string.feature_development')) 174 }) 175 Image($r('app.media.ic_public_more')) 176 .width($r('app.integer.layout_size_24')) 177 .height($r('app.integer.layout_size_24')) 178 .margin({ left: $r('app.integer.layout_size_24') }) 179 .onClick(() => { 180 promptActionFn($r('app.string.feature_development')) 181 }) 182 } 183 .padding({ right: $r('app.integer.layout_size_12') }) 184 } 185 .width('90%') 186 .padding({ left: $r('app.integer.layout_size_12') }) 187 .margin({ top: $r('app.integer.layout_size_12'), bottom: $r('app.integer.layout_size_11') }) 188 .height($r('app.integer.layout_size_33')) 189 .justifyContent(FlexAlign.SpaceBetween) 190 } 191 .justifyContent(FlexAlign.Center) 192 .width('100%') 193 194 195 } 196} 197 198@Component 199struct CommentArea { 200 @State currentTabIndex: number = 1; 201 @Consume commentDataSource: CommentData; 202 203 async aboutToAppear() { 204 await makeCommentDataLocal(this.commentDataSource); 205 } 206 207 // 设置tabBar样式的位置、未选中图片、选中图片及文字显示的参数 208 @Builder 209 TabBuilder(text: Resource, index: number) { 210 Column() { 211 Text(text) 212 .fontSize($r('app.integer.layout_size_21')) 213 .fontColor(this.currentTabIndex === index ? $r('app.color.font_color_blue') : $r('app.color.font_color_datetime')) 214 .padding({ top: $r('app.integer.layout_size_10'), bottom: $r('app.integer.layout_size_10') }) 215 .border({ 216 width: { bottom: this.currentTabIndex === index ? $r('app.integer.layout_size_4') : 0 }, 217 color: { bottom: $r('app.color.font_color_blue') }, 218 radius: { bottomLeft: $r('app.integer.layout_size_2'), bottomRight: $r('app.integer.layout_size_2') } 219 }) 220 }.margin({ right: $r('app.integer.layout_size_20') }) 221 } 222 223 build() { 224 Column() { 225 Row() { 226 Row() { 227 this.TabBuilder($r('app.string.share_count'), Constants.TAB_INDEX_0) 228 this.TabBuilder($r('app.string.comment_count'), Constants.TAB_INDEX_1) 229 } 230 231 Row() { 232 Text($r('app.string.like_count')) 233 .fontSize($r('app.integer.layout_size_21')) 234 .fontColor($r('app.color.font_color_datetime')) 235 } 236 } 237 .height(56) 238 .width('100%') 239 .justifyContent(FlexAlign.SpaceBetween) 240 241 Row() { 242 Row() { 243 Image($r('app.media.sequence')) 244 .width($r('app.integer.layout_size_21')) 245 .height($r('app.integer.layout_size_21')) 246 .margin({ right: $r('app.integer.layout_size_12') }) 247 Text($r('app.string.hot')) 248 .fontFamily('HarmonyHeiTi-Medium') 249 .fontSize($r('app.integer.layout_size_16')) 250 .fontColor($r('app.color.font_color_blue')) 251 } 252 }.width('100%') 253 .margin({ top: $r('app.integer.layout_size_10'), bottom: $r('app.integer.layout_size_10') }) 254 .justifyContent(FlexAlign.End) 255 .onClick(() => { 256 promptActionFn($r('app.string.feature_development')); 257 }) 258 259 List() { 260 LazyForEach(this.commentDataSource, (item: Trends, index: number) => { 261 ListItem() { 262 CommentItem({ commentsData: item, itemIndex: index }) 263 } 264 }, (item: Trends) => JSON.stringify(item)) 265 }.cachedCount(4) 266 .width('100%') 267 }.padding({ left: $r('app.integer.layout_size_20'), right: $r('app.integer.layout_size_20') }) 268 269 } 270} 271 272@Component 273struct CommentItem { 274 // 初始化断点 275 @StorageLink('currentBreakpoint') currentBreakpoint: string = 'sm'; 276 // 初始化评论数据 277 private commentsData: Trends = new Trends(new UserInfo(0, $r('app.media.photo115'), '', '', ''), new ContentsType('', [], []), '', 0, 0, 0) as Trends; 278 private itemIndex: number = 0; 279 280 /** 281 * 加载聊天列表数据,到参数传入的懒加载数据列表中 282 * @param count 数值 283 */ 284 handleCount(count: number) { 285 if (count > Constants.UNIT_10000) { 286 return `${(count / Constants.UNIT_10000).toFixed(1)}w`; 287 } else if (count > Constants.UNIT_1000 && count < Constants.UNIT_10000) { 288 return `${(count / Constants.UNIT_1000).toFixed(1)}k`; 289 } else { 290 return count.toString() 291 } 292 } 293 294 build() { 295 Row() { 296 Row() { 297 Image(this.commentsData.user.userImage) 298 .width($r('app.integer.layout_size_42')) 299 .height($r('app.integer.layout_size_42')) 300 .borderRadius($r('app.integer.layout_size_21')) 301 Column() { 302 Row() { 303 Text(this.commentsData.user.userName) 304 .fontSize($r('app.integer.layout_size_18')) 305 .fontFamily('HarmonyHeiTi-Medium') 306 .width(this.currentBreakpoint === 'sm' ? $r('app.integer.layout_size_236') : $r('app.integer.layout_size_260')) 307 Row() { 308 Image($r('app.media.ic_thumbsup')) 309 .opacity($r('app.float.icon')) 310 .width($r('app.integer.layout_size_28')) 311 .height($r('app.integer.layout_size_26')) 312 .margin({ left: $r('app.integer.layout_size_10') }) 313 .onClick(() => { 314 promptActionFn($r('app.string.feature_development')) 315 }) 316 Text(this.handleCount(this.commentsData.likeCount)) 317 .margin({ right: $r('app.integer.layout_size_24') }) 318 .width($r('app.integer.layout_size_38')) 319 .textAlign(TextAlign.Center) 320 .opacity($r('app.float.opacity')) 321 Image($r('app.media.ic_share')) 322 .opacity($r('app.float.icon')) 323 .width($r('app.integer.layout_size_24')) 324 .height($r('app.integer.layout_size_24')) 325 .margin({ right: $r('app.integer.layout_size_2') }) 326 .onClick(() => { 327 promptActionFn($r('app.string.feature_development')) 328 }) 329 }.width($r('app.integer.layout_size_122')).alignItems(VerticalAlign.Center) 330 } 331 332 Row() { 333 Text(this.commentsData.dateTime) 334 .fontSize($r('app.integer.layout_size_16')) 335 .fontColor($r('app.color.font_color_datetime')) 336 337 Text(this.commentsData.user.userType) 338 .fontSize($r('app.integer.layout_size_16')) 339 .fontColor($r('app.color.font_color_datetime')) 340 .margin({ left: $r('app.integer.layout_size_6') }) 341 } 342 .margin({ top: $r('app.integer.layout_size_6') }) 343 344 Text(this.commentsData.contents.text) 345 .fontSize($r('app.integer.layout_size_21')) 346 .fontFamily('HarmonyHeiTi') 347 .margin({ top: $r('app.integer.layout_size_6') }) 348 if (this.itemIndex === 1) { 349 Text($r('app.string.comments')) 350 .opacity($r('app.float.opacity')) 351 .width('100%') 352 .height($r('app.integer.layout_size_42')) 353 .fontFamily('HarmonyHeiTi') 354 .backgroundColor('#fff5f5f5') 355 .borderRadius($r('app.integer.layout_size_6')) 356 .padding({ left: $r('app.integer.layout_size_16') }) 357 .margin({ top: $r('app.integer.layout_size_12') }) 358 } 359 } 360 .alignItems(HorizontalAlign.Start) 361 .justifyContent(FlexAlign.Start) 362 .margin({ left: $r('app.integer.layout_size_10') }) 363 .padding({ bottom: $r('app.integer.layout_size_16') }) 364 .border({ 365 width: { bottom: Constants.BORDERWIDTH }, 366 color: { bottom: $r('app.color.border_color') }, 367 }) 368 }.alignItems(VerticalAlign.Top) 369 }.width('100%') 370 .justifyContent(FlexAlign.SpaceBetween) 371 .margin({ top: $r('app.integer.layout_size_10'), bottom: $r('app.integer.layout_size_10') }) 372 } 373} 374