1/** 2 * Copyright (c) 2022 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 router from '@system.router'; 16import ConListController from './conversationListController'; 17import DeviceUtil from '../../utils/DeviceUtil'; 18import HiLog from '../../utils/HiLog' 19import { DeleteDialog } from '../../views/MmsDialogs'; 20import { MmsListItem } from '../../views/MmsListItem'; 21import { MoreMenu } from '../../views/MmsMenu'; 22 23const TAG = 'ConversationList'; 24 25@Component 26export default struct ConversationList { 27 @Link @Watch('changeSelectState') mConListCtrl: ConListController; 28 private dialogAlignment: DialogAlignment = DeviceUtil.isTablet() ? DialogAlignment.Center : DialogAlignment.Bottom; 29 private dialogOffset: Offset = DeviceUtil.isTablet() ? { dx: 0, dy: 0 } : { dx: 0, dy: -12 }; 30 private dialogGridCount: number = 4; 31 delDialogController: CustomDialogController = null; 32 @State mIsMultipleSelectState: boolean = false; 33 @Provide menuItems: Array<any> = []; 34 35 changeSelectState() { 36 this.mIsMultipleSelectState = this.mConListCtrl.isMultipleSelectState; 37 this.menuItems = [ 38 { 39 value: $r('app.string.delete'), 40 action: () => { 41 this.mConListCtrl.showMultipleSelectView(); 42 }, 43 enabled: this.mConListCtrl.conversationListDataSource.totalCount() == 0 ? false : true 44 }, 45 { 46 value: $r('app.string.markAllAsRead'), 47 action: () => { 48 this.mConListCtrl.clickToMarkAllAsRead(); 49 }, 50 enabled: this.mConListCtrl.unreadTotal == 0 ? false : true 51 }, 52 { 53 value: $r('app.string.settings'), 54 action: () => { 55 this.mConListCtrl.jumpToSettingsPage(); 56 }, 57 enabled: true 58 } 59 ]; 60 // @ts-ignore 61 this.forceCompleteRerender(true) // recusvise 62 } 63 64 /** 65 * The function executes after a new instance of the custom component is created and before its build function 66 * is executed. 67 * You can change the state variable in the aboutToAppear function, and these changes will take effect in 68 * subsequent executions of the build function. 69 */ 70 aboutToAppear() { 71 this.delDialogController = new CustomDialogController({ 72 builder: DeleteDialog({ 73 cancel: () => { 74 this.mConListCtrl.deleteDialogCancel() 75 }, 76 confirm: () => { 77 this.mConListCtrl.deleteDialogConfirm() 78 }, 79 msg: this.mConListCtrl.strMsgDeleteDialogTip, 80 hasLockMsg: this.mConListCtrl.hasLockMsg, 81 setSelectLock: () => { 82 this.mConListCtrl.setSelectLock() 83 }, 84 isSelectLockMsg: this.mConListCtrl.isSelectLockMsg, 85 setSelectLockChange: (isOn: boolean) => { 86 this.mConListCtrl.setSelectLockChange(isOn) 87 } 88 }), 89 autoCancel: false, 90 alignment: this.dialogAlignment, 91 offset: this.dialogOffset, 92 gridCount: this.dialogGridCount 93 }); 94 95 this.mConListCtrl.registerDataChangeObserver(this.onContactChange, getContext(this)); 96 } 97 98 onContactChange = () => { 99 this.mConListCtrl.messageList = []; 100 this.mConListCtrl.requestItem(); 101 } 102 103 /** 104 * Function executes before custom component destructor consumption. 105 * Allow changes to state variables in the aboutToDisappear function, especially changes to the @Link variable, 106 * can cause erratic application behavior. 107 */ 108 aboutToDisappear() { 109 this.mConListCtrl.unregisterDataChangeObserver(this.onContactChange, getContext(this)) 110 this.delDialogController = null; 111 } 112 113 build() { 114 Stack() { 115 Flex({ 116 direction: FlexDirection.Column, 117 justifyContent: FlexAlign.Start, 118 alignItems: ItemAlign.Start 119 }) { 120 Column() { 121 // Menu Bar 122 Row() { 123 if (!this.mConListCtrl.isMultipleSelectState) { 124 Blank() 125 Image($rawfile('icon/ic_public_add.svg')) 126 .width($r('app.float.icon_side_length_medium')) 127 .height($r('app.float.icon_side_length_medium')) 128 .onClick(() => { 129 // The page for creating an SMS message is displayed. 130 router.push( 131 { 132 uri: 'pages/conversation/conversation', 133 params: { 134 isNewMsg: true 135 } 136 }) 137 }) 138 Column() { 139 MoreMenu() 140 } 141 .margin({ left: $r('app.float.action_bar_space') }) 142 } else { 143 Image($rawfile('icon/ic_public_cancel.svg')).height('24vp').width('24vp') 144 .onClick(() => { 145 this.mConListCtrl.onBackPress() 146 }) 147 Text(this.mConListCtrl.conversationSelectedNumber === 0 ? 148 $r('app.string.msg_unselected_tip') : 149 $r('app.string.msg_selected_tip', this.mConListCtrl.conversationSelectedNumber)) 150 .fontSize('20fp') 151 .fontWeight(FontWeight.Bold) 152 .margin({ left: 16 }) 153 } 154 } 155 .width('100%') 156 .height($r('app.float.action_bar_height')) 157 158 // Title bar 159 Column() { 160 if (!this.mConListCtrl.isMultipleSelectState) { 161 Row() { 162 Text($r('app.string.messages')) 163 .fontSize($r('app.float.list_title_font_size_large')) 164 .fontColor($r('sys.color.ohos_id_color_foreground')) 165 .fontWeight(FontWeight.Bold) 166 .lineHeight(41) 167 }.margin({ top: 8 }) 168 169 // Unread Message 170 Text($r('app.string.unread_messages', String(this.mConListCtrl.unreadTotal))) 171 .fontSize($r('sys.float.ohos_id_text_size_over_line')) 172 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 173 .fontWeight(FontWeight.Regular) 174 .margin({ top: 2 }) 175 .visibility(this.mConListCtrl.unreadTotal == 0 ? Visibility.None : Visibility.Visible) 176 } 177 } 178 .height(this.mConListCtrl.unreadTotal == 0 ? 56 : $r('app.float.message_bar_height')) 179 .visibility(this.mConListCtrl.isMultipleSelectState 180 ? Visibility.None : Visibility.Visible) 181 } 182 .alignItems(HorizontalAlign.Start) 183 .flexShrink(0) 184 185 if (!(this.mConListCtrl.hasNoOrdinaryMsg && !(this.mConListCtrl.hasAggregate && 186 this.mConListCtrl.hasInfoMsg && this.mConListCtrl.isSearchStatus))) { 187 Column() { 188 //Search box 189 // @ts-ignore 190 Row() { 191 if (this.mConListCtrl.messageList.length != 0) { 192 Image($rawfile('icon/ic_message_search.svg')) 193 .width(17) 194 .height(18) 195 .fillColor($r('sys.color.ohos_id_color_activated')) 196 .margin({ left: 11.5 }) 197 198 Text('搜索联系人') 199 .fontSize('16fp') 200 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 201 .margin({ left: 7.5 }) 202 } 203 } 204 .visibility(Visibility.None) 205 .height(40) 206 .width('100%') 207 .margin({ top: 8, bottom: 8 }) 208 .borderWidth(1.5) 209 .borderRadius(20) 210 .borderColor('#33182431') 211 212 List() { 213 if (this.mConListCtrl.hasAggregate && this.mConListCtrl.hasInfoMsg && 214 this.mConListCtrl.isSearchStatus) { 215 ListItem() { 216 Column() { 217 Row() { 218 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center }) { 219 if (this.mConListCtrl.unreadTotalOfInfo > 0) { 220 Text(this.mConListCtrl.unreadTotalOfInfo < 100 ? 221 this.mConListCtrl.unreadTotalOfInfo.toString() : '99+') 222 .fontSize(10) 223 .align(Alignment.Center) 224 .padding({ left: 5, right: 5 }) 225 .height(20) 226 .backgroundColor($r('sys.color.ohos_id_color_badge_red')) 227 .fontColor($r('sys.color.ohos_id_color_background')) 228 .zIndex(2) 229 .position({ x: '60%', y: '8%' }) 230 .border({ 231 width: 2, 232 color: $r('sys.color.ohos_id_color_background'), 233 radius: 50 234 }) 235 } 236 Image($rawfile('icon/entrance_icon01.svg')) 237 .width('40vp') 238 .height('40vp') 239 }.width('40vp').height('64vp') 240 241 Column() { 242 Row() { 243 Text($r('app.string.infoMessages')) 244 .fontSize('16fp') 245 .fontColor($r('sys.color.ohos_id_color_text_primary')) 246 .fontWeight(FontWeight.Medium) 247 Blank() 248 if (this.mConListCtrl.unreadTotalOfInfo > 0) { 249 Text(this.mConListCtrl.unreadTotalOfInfo + '') 250 .height('64vp') 251 .margin({ 252 right: $r('app.float.settings_item_status_title_margin_right') 253 }) 254 .fontSize($r('app.float.settings_item_secondary_title_font_size')) 255 .fontWeight(FontWeight.Regular) 256 .fontColor($r('sys.color.ohos_id_color_text_secondary')) 257 Image($rawfile('icon/ic_next.svg')) 258 .width($r('app.float.settings_item_next_image_width')) 259 .height($r('app.float.settings_item_next_image_height')) 260 } 261 } 262 .width('100%') 263 .height('100%') 264 .margin({ left: '4vp' }) 265 }.layoutWeight(1) 266 .height('100%') 267 .padding({ left: '12vp' }) 268 }.height('64vp') 269 .width('100%') 270 .onClick(() => { 271 this.mConListCtrl.clickToInfoMessages(this.mConListCtrl.hasAggregate, 272 this.mConListCtrl.hasInfoMsg, this.mConListCtrl.isSearchStatus) 273 }) 274 } 275 }.opacity(this.mConListCtrl.isMultipleSelectState ? 0.4 : 1) 276 } 277 278 LazyForEach(this.mConListCtrl.conversationListDataSource, (item: any, index: number) => { 279 ListItem() { 280 MmsListItem({ 281 item: item, 282 isShowHead: this.mConListCtrl.isShowContactHeadIcon, 283 isMultipleSelectState: this.mIsMultipleSelectState, 284 onClickHead: (event: ClickEvent) => { 285 this.mConListCtrl.clickToGroupDetail(item.index); 286 }, 287 onClickBody: (event: ClickEvent) => { 288 this.mConListCtrl.clickInfoToConversation(item.index); 289 }, 290 onItemLongPress: (event: GestureEvent) => { 291 this.mConListCtrl.conversationLongPress(item.index); 292 }, 293 onTouchStart: (event: GestureEvent) => { 294 this.mConListCtrl.touchStart(event, item.index); 295 }, 296 onTouchUpdate: (event: GestureEvent) => { 297 this.mConListCtrl.touchMove(event, item.index); 298 // @ts-ignore 299 this.forceCompleteRerender(true) // recusvise 300 }, 301 onTouchEnd: (event: GestureEvent) => { 302 this.mConListCtrl.touchEnd(event, item.index); 303 // @ts-ignore 304 this.forceCompleteRerender(true) // recusvise 305 }, 306 onClickFirstSlipBtn: (event: ClickEvent) => { //Read 307 this.mConListCtrl.markAllAsReadByIndex(item.index); 308 }, 309 onClickSecondSlipBtn: (event: ClickEvent) => { //Delete 310 this.mConListCtrl.deleteAction(item.index); 311 this.delDialogController.open(); 312 } 313 }) 314 }.width('100%') 315 .height('64vp') 316 }, (item: any) => JSON.stringify(item)) 317 } 318 .edgeEffect(EdgeEffect.Spring) 319 .width('100%') 320 .align(Alignment.Top) 321 .divider({ 322 strokeWidth: 1, 323 startMargin: this.mConListCtrl.isShowContactHeadIcon ? 52 : 12, 324 endMargin: 0 325 }) 326 .flexShrink(1) 327 328 Blank() 329 330 /*Select All Delete button at the bottom*/ 331 if (this.mConListCtrl.isMultipleSelectState) { 332 Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) { 333 Column() { 334 Image($rawfile('icon/ic_public_delete.svg')).height(24).width(24) 335 Text($r('app.string.delete')).fontSize(10).margin({ top: 3 }).lineHeight(13) 336 } 337 .width('50%') 338 .onClick(() => { 339 this.mConListCtrl.clickConversationDelete(); 340 this.delDialogController.open(); 341 }) 342 .enabled(!(this.mConListCtrl.conversationSelectedNumber === 0)) 343 .opacity(this.mConListCtrl.conversationSelectedNumber == 0 ? 0.5 : 1) 344 .alignItems(HorizontalAlign.Center) 345 346 Column() { 347 Image(this.mConListCtrl.isConversationCheckAll ? 348 $rawfile('icon/ic_select_all_filled.svg') : $rawfile('icon/ic_select_all.svg')) 349 .height(24).width(24) 350 Text(this.mConListCtrl.isConversationCheckAll ? $r('app.string.msg_deselect_all') 351 : $r('app.string.msg_select_all')) 352 .fontSize(10) 353 .margin({ top: 3 }) 354 .lineHeight(13) 355 .fontColor(this.mConListCtrl.isConversationCheckAll ? 356 $r('sys.color.ohos_id_color_bottom_tab_text_on') : 357 $r('sys.color.ohos_id_color_bottom_tab_text_off')) 358 } 359 .width('50%') 360 .onClick(() => { 361 this.mConListCtrl.clickConversationCheckAll() 362 }) 363 .alignItems(HorizontalAlign.Center) 364 } 365 .width('100%') 366 .height(56) 367 .padding({ 368 left: $r('app.float.menu_layout_padding_left'), 369 right: $r('app.float.menu_layout_padding_right') 370 }) 371 .flexBasis(56) 372 .flexShrink(0) 373 .backgroundColor($r('sys.color.ohos_id_color_background')) 374 } 375 } 376 .width('100%') 377 .height('100%') 378 } 379 } 380 .width('100%') 381 .height('100%') 382 383 if (this.mConListCtrl.hasNoOrdinaryMsg && !(this.mConListCtrl.hasAggregate && 384 this.mConListCtrl.hasInfoMsg && this.mConListCtrl.isSearchStatus)) { 385 EmptyView().hitTestBehavior(HitTestMode.Transparent) 386 } 387 } 388 .width('100%') 389 .height('100%') 390 } 391} 392 393@Component 394struct EmptyView { 395 build() { 396 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 397 Column() { 398 Image($rawfile('icon/ic_massage_m.svg')) 399 .width($r('app.float.empty_image_width')) 400 .height($r('app.float.empty_image_height')) 401 Text($r('app.string.noMessages')) 402 .margin({ top: $r('app.float.empty_text_top_margin') }) 403 .fontWeight(FontWeight.Regular) 404 .fontFamily('HarmonyHeiTi') 405 .fontSize($r('app.float.conversation_list_no_message_fs')) 406 .fontColor($r('sys.color.ohos_id_color_text_tertiary')) 407 } 408 // .margin({ top: '40%' }) 409 .offset({ y: -60 }) 410 } 411 .height('100%') 412 .width('100%') 413 } 414}