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 && this.mConListCtrl.hasInfoMsg 186 && 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 if (this.mConListCtrl.hasNoOrdinaryMsg && !(this.mConListCtrl.hasAggregate && this.mConListCtrl.hasInfoMsg 383 && this.mConListCtrl.isSearchStatus)) { 384 EmptyView().hitTestBehavior(HitTestMode.Transparent) 385 } 386 } 387 .width("100%") 388 .height("100%") 389 } 390} 391 392@Component 393struct EmptyView { 394 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}